代码之家  ›  专栏  ›  技术社区  ›  coder_bro

Haskell-在另一种类型中使用一种数据类型

  •  0
  • coder_bro  · 技术社区  · 7 年前

    Haskell newbie;我想能够申报 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..)
    

    实现这一目标的正确途径是什么?

    声明列表为 data List = List [Val] 最终允许列表如下:

    我希望列表中的每个元素都是 Value 同类的

    1 回复  |  直到 7 年前
        1
  •  6
  •   luqui    7 年前

    有一个使用GADTs的解决方案。问题是 IntVal etc实际上不是类型,它们只是单个类型的构造函数(基本上也是支持模式匹配的函数) 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的空列表和float的空列表,例如。你也可以对List使用相同的GADT技巧

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

    但在这种情况下,我认为更好的设计可能更简单

    newtype List a = List [Val a]
    

    所有这些不同的设计之间的取舍实际上取决于你打算用它们做什么。

    推荐文章