是的。您可以使用廣義代數數據類型(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)
但是,這個方案是不是很好(因爲你需要添加更多的構造函數,如果以後你需要使用其他元素使用相同的樹型)。所以,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
這是,如果你真的想在data
聲明限制使用的類型的解決方案。不過,我想提出一個更簡單的解決方案:只需保留樹定義,並且如果您想要處理一個樹,其中節點預期包含數值的元組,則只需使用類型簽名來編寫函數:
someFun :: (Num a) => MMTree (a, a) -> r
創建一個私有類型類並僅爲這些類型實例化它。 – rightfold 2014-10-16 17:42:11