在GHC/Type families網頁上,它有一半關於類型系列有用的初始示例。如何編寫這個GHC類型系列示例的相關函數?
基本上,它說一個Char
列表可以用cons單元表示。 ()
的列表除了長度以外沒有任何有用的信息,所以我們可以按其長度來表示列表。
太棒了。那麼這個列表的其他執行情況如何?如何定義length
,以及如何定義!!
或fromList
?
在GHC/Type families網頁上,它有一半關於類型系列有用的初始示例。如何編寫這個GHC類型系列示例的相關函數?
基本上,它說一個Char
列表可以用cons單元表示。 ()
的列表除了長度以外沒有任何有用的信息,所以我們可以按其長度來表示列表。
太棒了。那麼這個列表的其他執行情況如何?如何定義length
,以及如何定義!!
或fromList
?
對於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 =()
只是小編:
你可以將XList a
保留爲非類型類型關聯類型族,並且只爲類型持有操作的類型XList
添加類型類型;例如:
{-# 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
謝謝。網頁以獨立版本啓動,而不是與類型類關聯。你能否說明獨立版本是如何定義的? – Ana
「關聯」類型和數據族差別很小。除了編譯器會在您實現類而不是系列(也可以具有關聯類型和數據族的默認值)時向您發出警告外,它們並非真正「關聯」。如果將'XList'移出類,這裏唯一的區別是語法:'數據XList ..其中...'成爲'數據實例XList ...其中...'並且它被移出實例聲明之外。 – user2407038