【问题标题】:An error with Haskell classes I fall all the time and can't understandHaskell 课程的一个错误我一直跌倒并且无法理解
【发布时间】:2009-11-21 21:07:47
【问题描述】:

我一直遇到一个错误,但不知道如何改正。给我这个错误的代码示例是:

class Someclass a where
    somefunc :: (Num b) => b -> a -> a

data Sometype = Somecons Int

instance Someclass Sometype where
    somefunc x (Somecons y) = Somecons (x+y)

错误信息是:

无法将预期类型“b”与推断类型“Int”匹配
'b' 是一个刚性类型变量,由 'somefunc' 的类型签名在 error.hs:3:21
在'(+)'的第二个参数中,即'y'
在 'Somecons' 的第一个参数中,即 '(x + y)'
在表达式中:Somecons (x + y)

我了解错误消息试图告诉我我使用了 Int 类型的名称,而他期望的名称为 (Num b) => b。我无法理解的是 Int 适合 (Num b)=>b。编译器不应该理解我告诉他的内容吗(对于这个特定的实例,b 应该是一个整数?我怎样才能使它适合?

评论: 当然,在这个具体的例子中,我可以用类型签名制作 somefunc:

somefunc :: a -> a-> a 

但假设我想要类似的东西:

data Newtype = Newcons (Int, Int) 

instance Someclass Newtype where
    somefunc x (Newtype (y,z) ) = Newtype (y+x, z)

当我尝试在 haskell 中做某事时,这种事情经常发生。

【问题讨论】:

  • 嗯...我猜你的意思是data ...而不是Data...
  • 是的,当然。谢谢指正。

标签: haskell class type-systems


【解决方案1】:

好吧,在使用universal quantification 考虑泛型符号时,您可以更清楚地说明这一点。

somefunc :: (Num b) => b -> a -> a

所以什么都没有

somefunc :: forall a b . Num b => b -> a -> a

这意味着您的类函数必须为any数字b定义。

代码

Data Sometype = Somecons Int

instance Someclass Sometype where
    somefunc x (Somecons y) = Somecons (x+y)

强制b 具有一个具体类型 - Int,这不符合适用于任何数字类型的要求。

你可能想要这样的东西

class Num b => SomeClass a b where
    somefunc :: b -> a -> a

instance Someclass Somecons Int where
    -- ...

【讨论】:

    【解决方案2】:

    +操作符的签名中可以看出问题:

    (+) :: Num a => a -> a -> a
    

    因此,当您在somefunc 中使用+Int 时,它会强制b 成为Int,因此somefunc 变为:

    somefunc :: Int -> Sometype -> Sometype
    

    要实现Someclass 类,somefunc 应具有此签名:

    somefunc :: Num b => b -> Sometype -> Sometype
    

    也就是说,它应该适用于任何作为Num 实例的类型。您的函数适用于Ints。

    【讨论】:

    • somefunc 不会变成:: Int -> Sometype -> Sometype 吗?
    【解决方案3】:

    你不能混合类型,如(+) :: a → a → a

    let x = 1.2::Double; y=2::Int in x + y
    

    这已经失败了。

    Num 太笼统了,如果您指定 x::Double,您可以通过显式的“类型转换”(fromIntegral) 使其工作

    instance Someclass Sometype where
        somefunc x (Somecons y) = Somecons (x + (fromIntegral y))
    

    我想你想要这样的东西

    instance Someclass Sometype where
    
        somefunc :: Int → Sometype → Int
        somefunc x (Somecons y) = Somecons (x + y)
    

    顺便说一句,您需要输入数据而不是数据 :-)

    【讨论】:

    • 箭头很好,但在 Haskell 中没有这样的东西。这是->
    • 我知道,但在 Haskell 文献中使用印刷符号是常见的做法。一些 haskell 编辑器甚至以我展示的方式显示这些符号。
    • 我明白了。我更喜欢->,因为它可以复制粘贴(不是我认为任何人都会复制粘贴这种人为的示例代码)。
    【解决方案4】:

    继续以达里奥为例,您似乎要求的是:

    class Someclass a where
        somefunc :: exists b . (Num b) => b -> a -> a
    

    也就是说,而不是 "forall b . Num b => b" 暗示的“你选择一个类型,我的函数将起作用”的承诺,你想要 "exists b . (Num b) => b" 的“我将选择一个类型,所以我的函数将起作用”的承诺,费尔南德斯爵士提到的。 更重要的是,您没有展示您的约束 (Num b) => b 如何帮助您解决问题。

    真正有趣的情况是:你应该如何处理以下类型:

    data BMephType i o = BMT (i -> (o, BMephType i o))
    instance Someclass (BMephType (Complex Double -> String) String) where
    

    您的解决方案很可能涉及Complex Double。某处。如果它涉及Complex Double,而没有其他Num 类型,那么您正在寻找存在类型,而不是通用类型。

    【讨论】:

      猜你喜欢
      • 2020-07-25
      • 1970-01-01
      • 1970-01-01
      • 2012-01-25
      • 2018-02-18
      • 1970-01-01
      • 1970-01-01
      • 2013-08-14
      • 1970-01-01
      相关资源
      最近更新 更多