2013-04-07 22 views
5

Zaczynam uczyć się Haskella z "Learn You a Haskell for Great Good!" i popełniłem dziwny błąd, którego nie mogę znaleźć.Definicja funkcji w Haskell

Oto kod wpisałem:

let xs = [if x < 3 then "bang" else "boom" | x <- xs] 

A tekst błędu w GHCi:

No instance for (Num [Char]) 
arising from the literal `3' 
Possible fix: add an instance declaration for (Num [Char]) 
In the second argument of `(<)', namely `(3)' 
In the expression: x < (3) 
In the expression: if x < (3) then "bang" else "boom" 

Ale kiedy wpisać:

let boom xs = [if x < 3 then "bang" else "boom" | x <- xs] 

który jest przykład książki, nie mam żadnego problemu.

Czy ktoś mógłby wyjaśnić mój błąd?

+0

Dziękuję wam za odpowiedzi; uzupełniają się nawzajem. – guillaume8375

Odpowiedz

7

Spróbuj podać wyrażenie typu.

xs = [if x < 3 then "bang" else "boom" | x <- xs] 

Więc xs jest lista, nie wiem jeszcze co wpisać jej elementy mają, więc przyjrzyjmy się, że w przyszłym. Elementy listy są

if x < 3 then "bang" else "boom" 

który jest wyrazem typu String (aka [Char]).

Tak xs :: [String]. Ponieważ x z wyrażeniem opisującym elementy listy pochodzi z listy xs samej, jest to String też, i jest stosowany w porównaniu

if x < 3 

Teraz 3 jest liczbą całkowitą dosłowne, więc jest polimorficzny i ma typ

3 :: Num a => a 

Tak więc od wyrażenia x < 3 mamy

  • Num ograniczenie z literalnego,
  • typu String z faktu, że x jest rysowane z listy String s.

Tak więc potrzebujemy instancji Num dla String, aby uzyskać dobrze wypisane wyrażenie.

Zazwyczaj nie ma instancji Num dla String (jak mógłby wyglądać użyteczny?), Więc pojawia się błąd typu.

Jeśli xs jest argumentem funkcji,

boom xs = [if x < 3 then "bang" else "boom" | x <- xs] 

nie ma powodu, dlaczego typ x powinny być String, dlatego, że działa.

+0

Dziękuję wam za odpowiedzi; uzupełniają się nawzajem. – guillaume8375

13

Twoja definicja xs jest rekurencyjna, czyli używasz xs w swojej własnej definicji. Nie sądzę, żeby to było zamierzone.

Ponieważ używasz "bang" i "boom" wewnątrz listowych, Haskell wie, że xs musi być listą ciągów (bo xs jest równa wynikowi listy zrozumieniem). Dalej mówisz, że x jest elementem xs (x <- xs), więc x musi być ciągiem (a.k.a. [Char]). Jednak robisz x < 3, co oznacza, że ​​x jest liczbą. Komunikat o błędzie oznacza "ciąg nie jest liczbą".

+0

O cholera, pokonaj mnie kilka sekund .. +1 – jozefg

+0

Ładne zwięzłe wyjaśnienie błędu typu – Wes

0
let xs = ... 

oznacza xs równa listę „bang” S i/lub „boom” s, ale stan wskazuje, że te elementy powinny być badane na < 3, który jest zwykle wykonywane z numerów, a nie ciągi.

let boom xs =... 

równa funkcji „wysięgnik” z prawej strony równania w którym parametr „XS” to lista, z tym, że elementy do badania na < 3 są zabierane.