为什么这被认为是类型不匹配(或错误)?

时间:2018-03-22 22:47:55

标签: function haskell types type-declaration

这是我的代码导致后面的错误:

import Prelude hiding (div)

data Expr = Expr Op Int Int deriving (Show)
data Op = Add | Sub | Mul | Div deriving (Show)


evaluate :: (Num a) => Expr -> a
evaluate (Expr Add a b) = a + b
--evaluate (Expr Sub a b) = sub a b
--evaluate (Expr Mul a b) = mul a b
--evaluate (Expr Div a b) = div a b

错误讯息:

    exprs.hs:8:27: error:
    • Couldn't match expected type ‘a’ with actual type ‘Int’
      ‘a’ is a rigid type variable bound by
        the type signature for:
          evaluate :: forall a. Num a => Expr -> a
        at exprs.hs:7:1-32
    • In the expression: a + b
      In an equation for ‘evaluate’: evaluate (Expr Add a b) = a + b
    • Relevant bindings include
        evaluate :: Expr -> a (bound at exprs.hs:8:1)
  |
8 | evaluate (Expr Add a b) = a + b
  |                           ^^^^^
Failed, 0 modules loaded.

但是,(+)函数的类型为(Num a) => a -> a -> a,并且 我在函数evaluate中匹配的模式有两个 Ints (a& b),这两个都是Num类型类的一部分。由于在&上调用(+)的结果b将是Int类型(来自Num类型类),这也是我声明我的evaluate函数的输出类型,为什么GHCi会给我这个错误?

请注意,如果我将evaluate的类型声明更改为

evaluate :: Expr -> Int

然后这个错误没有出现。

1 个答案:

答案 0 :(得分:4)

evaluate :: (Num a) => Expr -> a

指出对于具有a实例的任何类型Numevaluate可以返回a类型的值,给定Expr 1}}价值。但是根据Expr的定义,您只能返回Int,因此编译器会拒绝您的定义。

如果允许,你可以这样做:

evaluate (Expr Add 2 3) :: Double

你的定义无法满足。

如果允许Expr通过表达式类型进行参数化,则可以使用您的定义:

data Expr a = Expr Op a a deriving (Show)

evaluate :: (Num a) => Expr a -> a
evaluate (Expr Add a b) = a + b
...