[英]Modeling heterogenous graphs in Haskell
如何在haskell中對我稱之為“異構圖”的模型進行建模,以便在編譯時驗證圖的類型正確性?
為此,異構圖是一組節點,每個節點具有特定類型標簽和一組邊,每個邊具有源類型標簽和目標類型標簽。
我們希望靜態地確保在將邊添加到圖中時,該邊的源類型標簽與源節點的類型標簽匹配,並且該邊的目標類型標簽與目標節點的類型標簽匹配。 但是我們不希望以微不足道的方式做到這一點(通過強制整個圖形僅包含具有一個特定類型標簽的節點)。
我不確定如何在編譯時強制執行此操作 - 我認為它要求您的圖形完全是靜態的? - 但是在運行時使用Typeable
強制執行它是相對簡單的。 這是一個看起來像什么的草圖。 首先,我將從類型化的Node
和Edge
類型開始:
data Node a = Node a
data Edge a b = Edge !Int !Int
將它們包裹在存在物中:
{-# LANGUAGE ExistentialQuantification #-}
import Data.Typeable
data SomeNode
= forall a. (Typeable a)
=> SomeNode (Node a)
data SomeEdge
= forall a b. (Typeable a, Typeable b)
=> SomeEdge (Edge a b)
擁有使用存在量化類型的異構圖數據類型:
import Data.IntMap (IntMap)
-- Not a great representation, but simple for illustration.
data Graph = Graph !(IntMap SomeNode) [SomeEdge]
然后執行動態類型檢查的操作:
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
import qualified Data.IntMap as IntMap
addNode
:: forall a. (Typeable a)
=> Int -> a -> Graph -> Maybe Graph
addNode i x (Graph ns es) = case IntMap.lookup i ns of
-- If a node already exists at a given index:
Just (SomeNode (existing :: Node e)) -> case eqT @e @a of
-- Type-preserving replacement is allowed, but…
Just Refl -> Just $ Graph ns' es
-- …*type-changing* replacement is *not* allowed,
-- since it could invalidate existing edges.
Nothing -> Nothing
-- Insertion is of course allowed.
Nothing -> Just $ Graph ns' es
where
ns' = IntMap.insert i (SomeNode (Node x)) ns
-- To add an edge:
addEdge
:: forall a b. (Typeable a, Typeable b)
=> Edge a b -> Graph -> Maybe Graph
addEdge e@(Edge f t) (Graph ns es) = do
-- The ‘from’ node must exist…
SomeNode (fn :: Node tfn) <- IntMap.lookup f ns
-- …and have the correct type; and
Refl <- eqT @a @tfn
-- The ‘to’ node must exist…
SomeNode (tn :: Node ttn) <- IntMap.lookup t ns
-- …and have the correct type.
Refl <- eqT @b @ttn
pure $ Graph ns $ SomeEdge e : es
現在這成功了:
pure (Graph mempty mempty)
>>= addNode 0 (1 :: Int)
>>= addNode 1 ('x' :: Char)
>>= addEdge (Edge 0 1 :: Edge Int Char)
但改變Int
/ Char
的Edge Int Char
無效類型,或0
/ 1
無效的指數,將失敗並返回Nothing
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.