Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function definition in Haskell

I'm beginning to learn Haskell with "Learn You a Haskell for Great Good!" and I've made a strange mistake, which I can't find the reason for.

Here is the code I typed:

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

And the the text of the error in 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"

But when I type:

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

which is the example of the book, I don't have any problem.

Could someone explain my mistake?

like image 735
guillaume8375 Avatar asked Apr 07 '13 20:04

guillaume8375


People also ask

What are function types in Haskell?

Functions can also be passed as arguments or returned (as we have seen). Their types are given in the type signature. *Main> :t map map :: (a -> b) -> [a] -> [b] *Main> :t filter filter :: (a -> Bool) -> [a] -> [a] flip_args :: (a -> b -> c) -> b -> a -> c flip_args f x y = f y x.

How do you create a function in Haskell?

In most imperative languages functions are called by writing the function name and then writing its parameters in parentheses, usually separated by commas. In Haskell, functions are called by writing the function name, a space and then the parameters, separated by spaces.

What is function composition in Haskell?

Composing functions is a common and useful way to create new functions in Haskell. Haskell composition is based on the idea of function composition in mathematics. In mathematics, if you have two functions f(x) and g(x), you compute their composition as f(g(x)). The expression f(g(x)) first calls g and then calls f.


2 Answers

Your definition of xs is recursive, that is you're using xs inside its own definition. I don't think that's what you intended.

Since you're using "bang" and "boom" inside the list comprehensions, Haskell knows that xs must be a list of strings (because xs is equal to the result of the list comprehension). Further you say that x is an element of xs (x <- xs), so x must be a String (a.k.a. [Char]). However you do x < 3, which implies that x is a number. The error message means "a String is not a number".

like image 101
sepp2k Avatar answered Sep 24 '22 21:09

sepp2k


Try to give the expression a type.

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

So xs is a list, we don't know yet what type its elements have, so let's look at that next. The list elements are

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

which is an expression of type String (aka [Char]).

So xs :: [String]. Since the x from the expression describing the list elements is taken from the list xs itself, it is a String too, and is used in the comparison

if x < 3

Now, 3 is an integer literal, thus it is polymorphic and has type

3 :: Num a => a

So from the expression x < 3, we have

  • a Num constraint from the literal,
  • the type String from the fact that x is drawn from a list of Strings.

Thus we need a Num instance for String to have a well-typed expression.

Usually, there is no Num instance for String (what would a useful one look like?), so you get a type error.

If xs is the argument of a function,

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

there is no reason why the type of x should be String, hence that works.

like image 41
Daniel Fischer Avatar answered Sep 25 '22 21:09

Daniel Fischer