为什么ghci给我一个"1 ++ 2"而不是ragequitting的类型?

Dav*_*ave 25 haskell

GHCI会给我一个类型1 ++ 2:

$ ghci
GHCi, version 7.4.2: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> :t 1 ++ 2
1 ++ 2 :: Num [a] => [a]
Run Code Online (Sandbox Code Playgroud)

但这显然是错误的.如果我尝试评估它,而不是只是键入检查它,事情正确失败:

Prelude> 1 ++ 2

<interactive>:3:1:
    No instance for (Num [a0])
      arising from the literal `1'
    Possible fix: add an instance declaration for (Num [a0])
    In the first argument of `(++)', namely `1'
    In the expression: 1 ++ 2
    In an equation for `it': it = 1 ++ 2
Run Code Online (Sandbox Code Playgroud)

是什么赋予了?

Dan*_*her 25

但这显然是错误的.

不,这是完全正确的.

类型(++)

(++) :: [a] -> [a] -> [a]
Run Code Online (Sandbox Code Playgroud)

和整数文字的类型是

1 :: Num n => n
Run Code Online (Sandbox Code Playgroud)

因此[a],(++)必须具有的参数的类型Num n => n与文字所具有的类型一致

1 ++ 2 :: Num [a] => [a]
Run Code Online (Sandbox Code Playgroud)

如果您有一个包含Num实例的列表类型,那么也可以计算该表达式.

但是,默认情况下,没有Num可用的列表类型的实例,因此当您尝试评估它时,ghci会抱怨它找不到Num实例[a].

例如:

Prelude> instance Num a => Num [a] where fromInteger n = Data.List.genericReplicate n 1 

<interactive>:2:10: Warning:
    No explicit method or default declaration for `+'
    In the instance declaration for `Num [a]'

<interactive>:2:10: Warning:
    No explicit method or default declaration for `*'
    In the instance declaration for `Num [a]'

<interactive>:2:10: Warning:
    No explicit method or default declaration for `abs'
    In the instance declaration for `Num [a]'

<interactive>:2:10: Warning:
    No explicit method or default declaration for `signum'
    In the instance declaration for `Num [a]'
Prelude> 1 ++ 2 :: [Int]
[1,1,1]
Run Code Online (Sandbox Code Playgroud)

  • "无实例..."消息并不意味着表达式本质上不是很好的类型,它是(实际类型错误得到不同的消息); 通过添加缺少的实例,您可以(几乎总是)获取ghci来接受和评估它. (10认同)
  • 它推断(并检查)类型,只要它可以推断.它没有做的是检查当前在范围内的实例是否允许以产生良好类型的单态表达式的方式实例化类型变量.这很好,因为有时您想要检查表达式的类型,而没有定义必要的实例来评估这样的表达式.当要计算表达式时,必须实例化类型变量以获得单态类型,然后ghci查找必要的实例.如果缺少实例,则会报告. (3认同)

ale*_*tor 16

因为有人可以定义要被视为数字的列表:

instance Num a => Num [a] where
 (+) = zipWith (+)
 (*) = zipWith (*)
 (-) = zipWith (-)
 negate = map negate
 abs = map abs
 signum = map signum
 fromInteger x = [fromInteger x]
Run Code Online (Sandbox Code Playgroud)

然后你输入的内容就可以了

  1++2 == fromInteger 1++fromInteger 2 == [1]++[2]
Run Code Online (Sandbox Code Playgroud)

(并不是说这个Num实例会有意义..)

  • 您可以为所有应用程序`T`定义一个最合理的`Num`实例(包括`[]`和`(( - >)e)`):`instance(Num a)=> Num(T a)其中fromInteger =纯洁.fromInteger; 否定= liftA否定; (+)= liftA2(+); ...` (11认同)
  • @melpomene我认为具体的例子在这里最好. (2认同)