【问题标题】:Haskell - deriving show for polymorphic typesHaskell - 多态类型的衍生展示
【发布时间】:2014-12-04 05:14:24
【问题描述】:

首先,我的背景是 C++,所以尽量不要太用力地打我。

在这个人为的例子中,我试图定义一个看起来像这样的多态类型:

data T x y
    = Cons1 x
    | Cons2 y
    | Neither
    deriving (Show)

我想要一个数据类型,它包含xy 类型或两者都不包含的值。 Maybe a 的一种变体。当我尝试这样做时:

main = do
    let v = Cons1 1
    putStrLn (show v)

出现了一些歧义:

No instance for (Show y0) arising from a use of `show'
The type variable `y0' is ambiguous
Note: there are several potential instances:
  instance (Show x, Show y) => Show (T x y)
    -- Defined at C:\Projects\Private\Haskell\Play\play.hs:14:27
  instance Show Double -- Defined in `GHC.Float'
  instance Show Float -- Defined in `GHC.Float'
  ...plus 25 others
In the first argument of `putStrLn', namely `(show t)'
In a stmt of a 'do' block: putStrLn (show t)
In the expression:
  do { let t = Cons1 1;
       putStrLn (show t) }

这是为什么?为什么会有歧义? Cons1 1 中的1 是从我理解的一个数字中得出的,它们都派生出Show。我认为构造函数本身充当了鉴别器,使Cons1 1 /= Cons2 1

【问题讨论】:

    标签: haskell


    【解决方案1】:

    使用Cons1 1,编译器只能在data T x y 中派生x 类型,而无法推断yx 变成了Num a,但是y 呢?在这种情况下,您需要手动指定它:

    main = do
        let v = (Cons1 1 :: T Int Int) -- just an example
        putStrLn (show v)
    

    在某些情况下,如果您使用显式函数类型,编译器将能够自动推断它。但在这种情况下,它确实没有任何提示。

    这与 Nothing 本身是模棱两可的一样。是Maybe StringMaybe IntMaybe Double,...?

    【讨论】:

    • 如果我注释掉打印行,编译器会接受它。编译器是否如此懒惰以至于在我调用 show 之前甚至不会生成 show 函数?另外,您将如何为这样的类型建模?我觉得我的例子很糟糕!
    • @JörgenSigvardsson 很奇怪。它应该生成“'do' 块中的最后一条语句必须是表达式”编译错误。你的类型不是坏的形式。 Either 的建模方式几乎相同(两个类型和每个类型的两个类型构造函数)。
    • 我将打印的表达式替换为空字符串,而不是删除。很抱歉混淆了这件事。
    猜你喜欢
    • 2011-01-18
    • 2018-01-11
    • 2017-10-02
    • 1970-01-01
    • 2022-10-20
    • 1970-01-01
    • 2017-01-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多