如何为这个GHC类型系列示例编写相关函数?

时间:2016-02-13 15:34:56

标签: haskell ghc type-families

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

2 个答案:

答案 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