[英]Elegant way to do associated "data items"
我正在嘗試關聯ContentType
的“數據項”及其內容:
data ContentType = MyInt | MyBool deriving ( Show )
data Encoding'
= EncodingInt [Int]
| EncodingBool [Bool]
chooseContentType :: IO ContentType
chooseContentType = undefined
我如何制作這樣的東西,但要進行類型檢查?
data Encoding a =
Encoding { contentType :: ContentType
, content :: [a]
}
您正在尋找的功能稱為廣義代數數據類型(簡稱 GADT)。 它是一個 GHC 擴展,因此您必須在文件頂部放置一個 pragma 才能使用它們。 (我還包括StandaloneDeriving
,因為我們將在一分鍾內使用它來獲取您的Show
實例)
{-# LANGUAGE GADTs, StandaloneDeriving #-}
現在您可以完全定義您的ContentType
類型。 這個想法是ContentType
由其參數的(最終)類型參數化,因此ContentType
將具有類型* -> *
(即它將采用類型參數)。
現在我們要用一些有趣的語法來編寫它。
data ContentType a where
MyInt :: ContentType Int
MyBool :: ContentType Bool
這表示MyInt
不僅僅是一個ContentType
; 這是一個ContentType Int
。 我們在ContentType
本身中保持類型信息有效。
現在基本上可以按照您的方式編寫Encoding
。
data Encoding a =
Encoding { contentType :: ContentType a
, content :: [a]
}
Encoding
還采用類型參數a
。 其內容必須是a
的列表,其內容類型必須是支持類型a
的內容類型。 由於我們的示例只定義了兩種內容類型,這意味着它必須是整數的MyInt
或布爾值的MyBool
,並且不支持其他編碼。
我們可以使用StandaloneDeriving
子句在ContentType
上恢復您的deriving (Show)
(這是我們在上述 pragma 中打開的第二個 GHC 擴展)
deriving instance Show (ContentType a)
這等同於您的deriving
子句,除了它位於自己的行之外,因為 GADT 語法實際上沒有將一個子句放在同一行的好地方。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.