在GHC/Type families网页上,它有半个例子,说明为什么类型系列很有用。
data family XList a
data instance XList Char = XCons !Char !(XList Char) | XNil
data instance XList () = XListUnit !Int
基本上,它表示Char
的列表可以由cons单元表示。 ()
列表除了长度之外没有任何有用的信息,因此我们可以按其长度表示列表。
那很好。那么这个列表的其余实现呢?如何定义length
,以及如何定义!!
或fromList
?
答案 0 :(得分:1)
XList Char
可能是:
{-# LANGUAGE TypeFamilies #-}
import Prelude hiding ((!!), length)
import qualified Prelude
class XList' a where
data family XList a :: *
fromList :: [a] -> XList a
length :: XList a -> Int
(!!) :: XList a -> Int -> a
instance XList' Char where
data XList Char = XCons !Char !(XList Char) | XNil
fromList [] = XNil
fromList (x:xs) = XCons x (fromList xs)
length XNil = 0
length (XCons x xs) = 1 + length xs
XNil !! _ = error "index error!"
(XCons x xs) !! 0 = x
(XCons x xs) !! k = xs !! (k - 1)
然后:
\> let a = fromList "wxyz"
\> :t a
a :: XList Char
\> length a
4
\> a !! 2
'y'
同样适用于XList ()
:
instance XList' () where
data XList () = XListUnit !Int
fromList a = XListUnit $ Prelude.length a
length (XListUnit n) = n
(XListUnit n) !! k
| k < 0 || n <= k = error "index error!"
| otherwise = ()
答案 1 :(得分:0)
只是一个小小的附录:
您可以将XList a
保留为非类型类关联的类型系列,只需为保存操作的XList
- y类型添加类型类; e.g:
{-# LANGUAGE TypeFamilies #-}
-- Original definition from your question
data family XList a
data instance XList Char = XCons !Char !(XList Char) | XNil
data instance XList () = XListUnit !Int
-- New class for XList-y types
class XListy a where
length :: XList a -> Int
(!!) :: XList a -> Int -> a
fromList :: [a] -> XList a
instance XListy () where
length (XListUnit n) = n
_ !! _ = ()
fromList xs = XListUnit $ Prelude.length xs