簡體   English   中英

Haskell-在另一種中使用一種數據類型

[英]Haskell - Using one data type kind in another

Haskell新手; 我希望能夠聲明Val ,它可以是IntVal, StringVal FloatVal ,也可以是一個List ,可以是StringList, IntList, FloatList ,其元素是(相應地): StringVal, IntVal and FloatVal 到目前為止我的嘗試:

data Val = IntVal Int
         | FloatVal Float
         | StringVal String deriving Show

data List = IntList [(IntVal Int)]
          | FloatList [(FloatVal Float)]
          | StringList [(StringVal String)] deriving Show

失敗並顯示以下錯誤:

    Not in scope: type constructor or class ‘IntVal’
    A data constructor of that name is in scope; did you mean DataKinds?

   data List = IntList [(IntVal Int)]

... (similarly for StringVal, FloatVal..)

什么是實現此目標的正確方法?

PS:將列表聲明為data List = List [Val]最終允許List如下:l = [(IntVal 10),(StringVal“ Hello”)],我不想允許。

我希望列表的每個元素都是相同的Value

有使用GADT的解決方案。 問題在於IntVal等實際上不是類型,它們只是單個類型Val構造函數(基本上也支持模式匹配的函數)。 因此,一旦創建了Val ,有關類型的值的信息就會在類型級別(即編譯時)完全丟失。

訣竅是用Val包含的類型標記Val

data Val a where
    IntVal :: Int -> Val Int
    FloatVal :: Float -> Val Float
    StringVal :: String -> Val String

然后,如果您有一個簡單列表[Val a] ,它將已經是同質的。 如果你必須:

data List = IntList [Val Int]
          | FloatList [Val Float]
          ...

這與“擦除”列表的類型略有不同,例如,它可以區分空白的int列表和空白的floats列表。 您也可以對List使用相同的GADT技巧

data List a where
    IntList :: [Val Int] -> List Int
    FloatList :: [Val Float] -> List Float
    ...

但在那種情況下,我認為更好的設計可能更簡單

newtype List a = List [Val a]

所有這些不同設計之間的權衡實際上取決於您打算如何處理它們。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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