Tuesday, October 13, 2009

Types and Type Classes

Important bit of info number one: Everything in Haskell has a type. (Except comments. That would be silly.)

Once you've got Haskell installed, you can run the interactive shell with ghci. Open that up. You should get some version info, some "I'm loading, hold your horses" kind of stuff, and then

Prelude>


(From here on, I'll just use > instead.)

Let's play around a bit.

> 3
3


Type in 3, you get 3. Not particularly exciting.

> 3+4
7


Slightly more interesting.

> "cake"
"cake"


Tasty.

> "cake" + 3

<interactive>:1:0:
No instance for (Num [Char])
arising from a use of `+' at :1:0-9
Possible fix: add an instance declaration for (Num [Char])
In the expression: "cake" + 3
In the definition of `it': it = "cake" + 3


Now that's interesting. "What are you doing?!" Haskell cries. "Why do you try to add 3 to cake? What does that even mean, you very silly person?" Haskell complains because the type of the function + (Yes, it's a function. You can do anything with it that you can do with any other function) doesn't match what it sees. Important Bit Of Information Number 1a: Functions have types. In ghci, you can find the type of something with :t. Like so:

> :t (+)
(+) :: (Num a) => a -> a -> a


Okay, first, why + is in parentheses. It's an infix function, and those need to be in parentheses to be passed around. Now, to explain the second line.

(+) :: (Num a) => a -> a -> a


First of all, Num. This is what's called a type class. Num is a class containing all the numeric types. (Num a) means that, for this type signature, a is a numeric type.
a -> a -> a
means that the function takes two arguments of type a and returns a value of type a. So, + is a function that takes two numeric arguments and returns a numeric value.

Let's play around a bit more with :t.

> :t 'e'
'e' :: Char


A character is denoted by single quotes.

> :t "cake"
"cake" :: [Char]


That's a list of characters. In Haskell, there's no difference between this and a string. (More on lists later)

> :t 3
3 :: (Num t) => t


Without any context, 3 doesn't have a specific type. There are quite a few numeric types, and Haskell doesn't know which one we want, so, for now, it's just some kind of number.

> :t succ
succ :: (Enum a) => a -> a


succ is a function that takes a value and returns the next one. Enum is a type class containing types where "next value" actually means something. You can use these types in ranges (more on that later).

 :t print
print :: (Show a) => a -> IO ()


print does exactly what you think it does. Show is a typeclass containing things you can print. The weird part here is
IO ()
This is what's called a monad. They're weird. Don't worry about them for now.

 :t (<)
(<) :: (Ord a) => a -> a -> Bool


< returns True if the first value is less, False otherwise. Bool is, obviously, the type for boolean values. Ord is the type class containing types whose values are in a defined order.

1 comment:

  1. Outstanding post, really clear and concise explanation of the basics of Haskell, it helped a lot!

    ReplyDelete