Gov*_*mar 3 haskell types tuples
我有一个树,旨在包含每个节点的元组:
-- Should be initialized with `a' as a tuple of (Int, Int) or (Float, Float)
data MMTree a = Empty | Node a (MMTree a) (MMTree a) deriving Show
Run Code Online (Sandbox Code Playgroud)
有没有什么办法来限制a,这样MMTree可以只与特定类型的初始化; 即,(Int, Int)或者(Float, Float)不是任何旧类型?
是.您可以使用广义代数数据类型(GADT,http://en.wikibooks.org/wiki/Haskell/GADT),它们可以完全满足您的需要(结果类型可以取决于使用的构造函数).作为一个简单的解决方案,您可以为每种可能的节点类型创建一个构造函数:
{-# LANGUAGE GADTs #-}
data MMTree a where
Empty :: MMTree a
NodeI :: (Int, Int) -> MMTree (Int, Int) -> MMTree (Int, Int) -> MMTree (Int, Int)
NodeF :: (Float, Float) -> MMTree (Float, Float) -> MMTree (Float, Float) -> MMTree (Float, Float)
Run Code Online (Sandbox Code Playgroud)
但是,这个解决方案不是很好(因为如果以后你需要为其他元素使用相同的树类型,你需要添加更多的构造函数).所以,DataKinds以及TypeFamilies救援:
{-# LANGUAGE GADTs #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeFamilies #-}
data TreeType
= TInt
| TFloat
type family Elem (t :: TreeType) where
Elem TInt = (Int, Int)
Elem TFloat = (Float, Float)
data MMTree (t :: TreeType) where
Empty :: MMTree a
Node :: Elem a -> MMTree a -> MMTree a -> MMTree a
test1 :: MMTree TInt
test1 = Node (1, 1) Empty Empty
test2 :: MMTree TFloat
test2 = Node (2.0, 3.0) Empty Empty
Run Code Online (Sandbox Code Playgroud)
如果您真的想在data声明中限制使用的类型,那么这就是解决方案.但是,我想建议一个更简单的解决方案:只保留树的定义,如果你想处理一个树,其中节点应该包含数值的元组,只需编写具有类型签名的函数:
someFun :: (Num a) => MMTree (a, a) -> r
Run Code Online (Sandbox Code Playgroud)