Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to use typeclasses?

Tags:

haskell

Usually when I create functions I don't know in which functions it is better to use typeclasses (Eq,Integral and etc.) because sometimes there is no need to use them like:

factorial :: Int -> Int 
bla bla bla 
bla bla bla

and

factorial :: (Integral a) => a -> a
bla bla bla
bla bla bla

I believe that the second one is just taking time and place but in elem function it is important to write Eq (below elleme is elem)

elemme :: Eq a => a -> [a] -> Bool
y `elemme` [] = False
y `elemme` (x:xs) = if y == x then True else y `elemme` xs 

Please advise me something about it. Thanks.

like image 251
user2999428 Avatar asked Mar 20 '26 17:03

user2999428


2 Answers

Typeclasses let you write more general functions. Haskell has great tools for letting you specify that a function works over all types, like

id :: a -> a
id a = a

But some things don't work over all types,

(==) :: Eq a => a -> a -> Bool

Without typeclasses, we'd either have to write a new == for each type,

eqInteger :: Integer -> Integer -> Bool

Or specify that all types are equatable and can be tested for equality. But then you could ask

id == const 1

So, when you find yourself wanting to specify that your function works over a subset of all types, go for typeclasses.

I often favor writing this more general functions even if I don't use them over more than one type since the more general the signature, the fewer options there are for the implementation, which makes it easier to know that I haven't done something silly like

id :: Integer -> Integer
id = (+1)

You're essentially stating that your function only requires X functions which makes it possible to get a compiler error for using the wrong function.

like image 189
Daniel Gratzer Avatar answered Mar 22 '26 12:03

Daniel Gratzer


One of the benefits I get out of making my functions as general as possible is that it often allows for use cases I didn't think of before. When you start making things general, you start coming up with weird uses for your functions.

You go, "But what if this value is a function?" Or "What if I allow this for any functor – what would be the result for other functors? Is it useful?" As it turns out, it is in a lot of cases! And this is one of the reasons Haskell is so great, in my opinion. It is easy to "accidentally" create very reusable functions.

In other languages, you design functions for specific purposes and use them that way. In Haskell, you design functions for specific purposes and give them a general type signature, and suddenly they work for a ton of cases you didn't design them for.


@jozefg made a great point about the generality restricting the possible implementations. I just want to give that more of a spotlight, because it is actually a very powerful concept. With a few general function, you can actually be completely sure what the function does only based on the type signature, because there's only one possible implementation for that general signature.

I recently encountered the signature

mystery :: (a -> b -> c) -> (a -> b) -> a -> c

which is interesting because we can actually figure out which function it is based on what it does. We have

mystery :: (a -> b -> c) -> (a -> b) -> a -> c
mystery    f                g           x = ...

and we need it to return a c value of some kind. The only way we can get a value of type c is by applying the function f to an a value and a b value. We already have a single a value – this is the x argument. So we can partially apply f x :: b -> c but we still need a b value to get the c value we want.

The solution, of course, is to apply g x to get a b value, which we then can stick into f, thus finally returning a c value. The description of this is a little complicated to follow, but if you work it out in your head you arrive at

mystery f g x = f x (g x)

which performs the same thing as the library function ap. (From Control.Applicative.)

It is very cool that you can figure out what a function does solely based on its type signature!

like image 20
kqr Avatar answered Mar 22 '26 12:03

kqr