2013-02-23 3 views
25

GHCI даст мне тип для 1 ++ 2:Почему ghci дает мне тип для «1 ++ 2» вместо ragequitting?

$ 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] 

Но это явно не так. Если я попытаюсь оценить его, вместо того, чтобы просто проверять его, все правильно работает:

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 

Что дает?

+8

+1 для названия – Mysticial

ответ

25

Но это, очевидно, неправильно.

Нет, это совершенно правильно.

Тип (++) является

(++) :: [a] -> [a] -> [a] 

и тип целочисленных литералов

1 :: Num n => n 

Таким образом, тип [a], что аргумент (++) должен быть объединен с типом Num n => n что буквальное имеет, давая

1 ++ 2 :: Num [a] => [a] 

, и если у вас есть тип списка с экземпляром 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] 
+0

Значит ли это, что ghci не полностью проверяет тип выражения? Каков шаг, который не делает ghci, чтобы перейти от Num [a] к «нет Num [a]»? – Dave

+3

Он выводит (и проверяет) тип, насколько это можно сделать. То, что он не делает, - это проверка того, будут ли экземпляры, находящиеся в настоящее время в области видимости, создавать экземпляры типов таким образом, чтобы обеспечить типизированное мономорфное выражение. Это хорошо, поскольку иногда вы хотите проверить, какой тип имеет выражение, не указав необходимые экземпляры для оценки такого выражения. Когда выражение должно быть оценено, переменные типа должны быть созданы для получения мономорфного типа, а затем ghci ищет необходимые экземпляры. Если экземпляры отсутствуют, это сообщается. –

+10

Сообщение «Нет экземпляра ...» не означает, что выражение по сути не очень хорошо напечатано, оно (ошибки реального типа получают разные сообщения); добавив недостающие экземпляры, вы можете (почти всегда) получить ghci, чтобы принять и оценить его. –

16

Потому что кто-то может определить списки, которые будут рассматриваться как номера:

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

Тогда что вы ввели будет работать, так как

1++2 == fromInteger 1++fromInteger 2 == [1]++[2] 

(Не то, чтобы этот пример Num имел смысл.)

+11

Вы можете определить наиболее чувствительный экземпляр «Num» для всех применений «T» (включая '[]' и '((->) e)'): 'instance (Num a) => Num (T a), где fromInteger = чистый. fromInteger; negate = liftA отрицать; (+) = liftA2 (+); ... ' – melpomene

+2

@melpomene Я думал, что конкретный пример будет лучше всего здесь. – aleator

Смежные вопросы