创建Ints和函数列表Int - > Int - >诠释

时间:2014-08-07 04:02:43

标签: 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 actual type `Integer -> Integer -> Integer'
In the expression: (+)
In the expression: [12, (+)]
In an equation for `tokens': tokens = [12, (+)]

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

2 个答案:

答案 0 :(得分:14)

您需要使用构造函数来获取类型Token的值。例如,12不属于Token类型,类型为Int(嗯,Num a => a)。同样,(+)不是令牌,而是函数Int -> Int -> Int。请注意Token /= Int -> Int -> Int

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

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

答案 1 :(得分:4)

正如托马斯所说,IntInt->Int->Int值不能有类型Token:每个Haskell值只有一个类型 1 ,没有这样的在Haskell中作为OO风格的子类型的东西。

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

  

前奏> :t 12
  12 :: Num a =>一个

这意味着,如果TokenNum类型,那么12实际上将是一个正确的值(它不会有Int类型,但Token 1}}马上!)为此,您可以编写

instance Num Token where
  fromInteger = Token . fromInteger

严格地说,你应该为Token实现加法,绝对值等,这不会很好。此外,(+)[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]String实际上属于同一类型,后者是刚刚定义为同义词type String = [Char]。 OTOH,datanewtype您总是定义 new (duh),因此会分开类型。