Haskell中的类出错

时间:2014-05-26 16:34:22

标签: haskell

我一直在尝试用一个小程序来学习haskell中的类来操纵线性方程的表示,但是我得到了一个我不明白的错误。有人可以告诉我为什么这个代码

{-# LANGUAGE FlexibleInstances #-}

data Line = Line { m :: Double, b :: Double } deriving( Show, Eq )

class Perpendicular a where
  perpendicular :: a -> Line

instance Perpendicular (Line -> Double) where
  perpendicular (Line m b) b2 = Line m2 b2
    where m2 = (-1/m)

给我这个错误

Couldn't match expected type `Line -> Double'
            with actual type `Line'
In the pattern: Line m b
In an equation for `perpendicular':
    perpendicular (Line m b) b2
      = Line m2 b2
      where
          m2 = (- 1 / m)
In the instance declaration for `Perpendicular (Line -> Double)'

看起来好像忽略了b2。

1 个答案:

答案 0 :(得分:5)

您已将实例编写为

instance Perpendicular (Line -> Double) where ...

这意味着a ~ (Line -> Double)perpendicular是一个类型为a -> Line的函数,因此对于此实例,它将具有具体类型(Line -> Double) -> Line。这意味着它的第一个参数必须是一个带Line并返回Double的函数。您已为其提供了Line m bb2参数,这意味着perpendicular应该具有类型Line -> Double -> Line,这是一种完全不同的类型。这是因为->右关联,这意味着以下类型是等价的

a ->  b ->  c -> d
a ->  b -> (c -> d)
a -> (b -> (c -> d))
a -> (b ->  c -> d)

但这些都不是

  a -> b  -> c  -> d   -- These are not equivalent!!
 (a -> b) -> c  -> d   -- These are not equivalent!!
((a -> b) -> c) -> d   -- These are not equivalent!!
 (a -> b  -> c) -> d   -- These are not equivalent!!

你想要的是一个带变量参数的函数。这在Haskell中不是最简单的事情,并且可能导致许多样板和复杂的数据结构,可能在牺牲类型安全性的同时损害效率。你可以通过利用元组来解决这个问题,比如

instance Perpendicular (Line, Double) where
    perpendicular (Line m b, b2) = Line (-1 / m) b2

instance Perpendicular Line where
    perpendicular line = perpendicular (line, 0 :: Double)

注意,这仍然需要FlexibleInstances,并且还需要0上的类型注释。这仍然使得类型组做了他们并不意味着的事情,但它是合法的代码。只要它没有声明的类型,你也必须注释一个值,例如。

> perpendicular (Line 1 0, 5 :: Double)
Line {m = -1.0, b = 5.0}
> perpendicular (Line 1 0, 5)
    No instance for (Perpendicular (Line, t0))
      arising from a use of `perpendicular'
    The type variable `t0' is ambiguous
    Possible fix: add a type signature that fixes these type variable(s)
    Note: there is a potential instance available:
      instance Perpendicular (Line, Double)
        -- Defined at <interactive>:11:10
    Possible fix:
      add an instance declaration for (Perpendicular (Line, t0))
    In the expression: perpendicular (Line 1 0, 5)
    In an equation for `it': it = perpendicular (Line 1 0, 5)