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

Function 为什么这被认为是类型不匹配(或错误)?,function,haskell,types,type-declaration,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 --evalu

这是导致以下错误的代码:

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
中匹配的模式有两个int(a和b),它们都是Num-typeclass的部分。由于在a&b上调用(+)的结果将是Int类型(来自Num typeclass),这也是我声明的
evaluate
函数的输出类型,为什么GHCi会给我这个错误

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

evaluate :: Expr -> Int
那么这个错误就不会出现了

evaluate :: (Num a) => Expr -> a
声明对于具有
Num
实例的任何类型
a
evaluate
可以在给定
Expr
值的情况下返回
a
类型的值。但是,给定
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
...
声明对于具有
Num
实例的任何类型
a
evaluate
可以在给定
Expr
值的情况下返回
a
类型的值。但是,给定
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
...

因此,具体来说,数据构造函数Expr Op Int只能有两个Int,这意味着函数定义中的(+)将始终返回一个Int,因此它与类型声明不匹配。。。我理解得对吗?@corecase-是的,没错-调用方可以选择类型
a
,而不是您的实现,因此您不能对其进行任何假设。@corecase该类型承诺,调用
evaluate
的任何人都可以选择数字返回类型(例如a
Double
)。因此,
evaluate
必须适应任何这样的选择,并且不能只涵盖
Int
的情况。因此,具体来说,数据构造函数Expr Op Int Int只能有两个Int,这反过来意味着函数定义中的(+)将始终返回一个Int,因此它与类型声明不匹配。。。我理解得对吗?@corecase-是的,没错-调用方可以选择类型
a
,而不是您的实现,因此您不能对其进行任何假设。@corecase该类型承诺,调用
evaluate
的任何人都可以选择数字返回类型(例如a
Double
)。因此,
evaluate
必须适应任何这样的选择,并且不能只涵盖
Int
情况。