Haskell 创建Int和函数列表Int->;Int->;Int

Haskell 创建Int和函数列表Int->;Int->;Int,haskell,Haskell,除了创建对列表进行简单操作的函数外,我对haskell还很陌生。我想创建一个列表,其中包含Int类型的内容和Int->Int->Int类型的函数 以下是我尝试过的: data Token = Value Int | Operator (Int -> Int -> Int) tokens :: [Token] tokens = [12, (+)] 但是我得到了以下错误 Couldn't match expected type `Token' with act

除了创建对列表进行简单操作的函数外,我对haskell还很陌生。我想创建一个列表,其中包含
Int
类型的内容和
Int->Int->Int
类型的函数

以下是我尝试过的:

data Token = Value Int | Operator (Int -> Int -> Int)

tokens :: [Token]
tokens = [12, (+)]
但是我得到了以下错误

Couldn't match expected type `Token'
            with actual type `Integer -> Integer -> Integer'
In the expression: (+)
In the expression: [12, (+)]
In an equation for `tokens': tokens = [12, (+)]

我不知道为什么这不起作用,有人能给我指出正确的方向吗?

您需要使用构造函数来获取
标记类型的值。例如,
12
不是类型
Token
,而是类型
Int
(嗯,
Num a=>a
)。类似地,
(+)
不是一个令牌,而是一个函数
Int->Int->Int
。注意,
Token/=Int->Int->Int

幸运的是,您已经定义了一些构造函数,例如
Value::Int->Token
Operator::(Int->Int->Int)->Token
。因此,使用我们得到的:

tokens :: [Token]
tokens = [Value 12, Operator (+)]

正如Thomas所说,一个
Int
Int->Int
值不能有类型
Token
:每个Haskell值正好有一个类型1,Haskell中没有OO风格的子类型

然而,Haskell类型(不仅仅是函数,还有任何东西!)可能是多态的。事实上,数字文字是多态的:

序曲>:t12
12::Num a=>a

这意味着,如果
Token
Num
类型,那么
12
实际上是一个正确的值(它不会有type
Int
,而是
Token
立即!)。要实现这一点,您可以编写

instance Num Token where
  fromInteger = Token . fromInteger
严格地说,您还应该为
令牌
实现加法、绝对值等,这不会很好。另外,
(+)
[Token]
中仍然无效。但是你可以写

tokens = [12, Operator(+)]
事实上,如果这应该是一个很长的列表,并且您希望代码保持简短,那么您可以使用一个相当讨厌的技巧,让您能够完全按照原来的方式编写代码:

mkToken :: TokenRep -> Token
mkToken f = f undefined undefined

type TokenRep = Token->Token->Token

instance Num Token where
  _ + _ = Operator (+)
  _ - _ = Operator (-)
  _ * _ = Operator (*)

instance Num TokenRep where       -- You need `-XFlexibleInstances` here
  fromInteger n _ _ = Value $ fromInteger n
然后

tokens = map mkToken [12, (+)]  -- Note that `12` has type `Token->Token->Token` here!
但实际上,这将是一个相当可怕的黑客



1单个类型可能有多个名称:
[Char]
字符串
实际上是同一类型,后者只是定义为同义词
类型字符串=[Char]
。OTOH,使用
数据
新类型
您总是在定义一个新的(duh)类型,因此是单独的类型。

啊,这很有意义。非常感谢。谢谢这有点让我不知所措,但一旦我对haskell有了更多的了解,再回头看看会很有用的。