簡體   English   中英

做關聯“數據項”的優雅方式

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM