したがって、この(非常に単純化された)コードに非常に似た状況があります。
import Data.Maybe
import Data.List
data Container a = Container [a]
-- Assumption: an Element can only obtained from a Container. The operation
-- guarentees the Element is in the Container.
data Element a = Element (Container a) a
-- This operation is only valid for Elements that have the same Container.
before :: Eq a => Element a -> Element a -> Bool
before (Element (Container xs) x) (Element (Container ys) y)
| xs == ys = fromJust (elemIndex x xs) < fromJust (elemIndex y xs)
| otherwise = error "Elements from different Containers"
before
Haskell の型システム (または GHC 拡張機能) を使用して、 および類似の操作がElement
異なる から を取得するのを制限するにはどうすればよいContainer
ですか? 私は調べていましGADTs
たDataKinds
が、まあ、それには長い時間がかかるので、いくつかの提案や指針を使用できます. (私が考えたがうまくいかなかった別のアイデア:ST
モナドのs
パラメーターと同様のトリックを使用する...)
依存型言語が必要になると結論付けたら、私は悲観的すぎますか? Element
依存型の型付けについての私の限られた理解が進むにつれて、型の値によって型にインデックスを付けようとしていると思うからですContainer
。
編集:余分な色のために、これはすべて最終的に発生します。これは、次のようなものを非常に定義しようとしているためです。
import Data.Function
import Data.Ix
-- I want to use Elements as Array indexes; so Elements need to know
-- their Container to calculate their Int
instance Eq a => Ix (Element a) where
-- Ignore how crap this code is
range (l, u) = map (getSibling l) [getIndex l .. getIndex u]
index (l,u) i = index (getIndex l, getIndex u) (getIndex i)
inRange (l,u) i = inRange (getIndex l, getIndex u) (getIndex i)
getIndex :: Eq a => Element a -> Int
getIndex (Element (Container xs) x) = fromJust $ elemIndex x xs
getList :: Element a -> [a]
getList (Element (Container xs) _) = xs
getSibling :: Element a -> Int -> Element a
getSibling (Element (Container xs) _) i = Element (Container xs) (xs!!i)
instance Eq a => Eq (Element a) where
(==) = (==) `on` getIndex
instance Eq a => Ord (Element a) where
compare = compare `on` getIndex
Element
このすべてのコードでは、異なる からのを決して「混在」させないようにする必要がありますContainer
。