ユニバース タイプとワーカー タイプがあります。労働者は宇宙を変えることができます。私が達成したいのは、そのユニバースのワーカーのみがユニバースを変更できるようにすることです (将来または過去のワーカーではありません)。
私が達成できる最高のものはこれです:
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
module Module(initialUniverse, doSomething, doStep) where
data Nat = Z | S Nat
data Universe (t :: Nat) = Universe {
_allWorkers :: [Worker t]
}
data Worker (t :: Nat) = Worker
initialUniverse :: Universe Z
initialUniverse = Universe [Worker]
doSomething :: Worker t -> Universe t -> Universe (S t)
doSomething = undefined
doStep :: Universe t -> Universe (S (S t))
doStep u = let w = head $ _allWorkers u
u2 = doSomething w u
w2 = head $ _allWorkers u2
u3 = doSomething w2 u2
in u3
に変更w2 = head $ _allWorkers u2
するw2 = head $ _allWorkers u
と、必要なコンパイルエラーが発生します。
私があまり気に入らないのは、各ユニバースにバージョンがアタッチされており、手動でインクリメントする必要があることです。明示的なバージョン管理を必要としない別の方法でこれを行うことはできますか? 型チェッカーが知っているdoSomething
関数が a を返すようにするようなものは、とは異なります。Universe otherType
otherType
t
御時間ありがとうございます。