Haskell ad hoc polymorphism

I'm trying to get my head around ad-hoc polymorphism in haskell, that is having the same function provide different behaviour for different argument types.

But while the following test code compiles

{-# LANGUAGE MultiParamTypeClasses #-}

class MyClass a b where
    foo :: a -> b

instance MyClass Bool Int where
    foo True = 0
    foo False = 1

instance MyClass Double Double where
    foo x = -x

if I try to call it using something like

foo True

ghci yells at me:

No instance for (MyClass Bool b0) arising from a use of `foo'
The type variable `b0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there is a potential instance available:
  instance MyClass Bool Int -- Defined at test.hs:6:10
Possible fix: add an instance declaration for (MyClass Bool b0)
In the expression: foo True
In an equation for `it': it = foo True

However, if I specify the return type, it works:

foo True :: Int -- gives 0

Why is this needed? The parameter type of Bool should be enough to resolve the ambiguity.

Also: Is this the "best" way to achieve similar behaviour? (without renaming the functions to fooBool and fooDouble)

Answers


The problem you're facing is that the overloading is determined by all of the types in the class—including ones that only appear as return types. You could have instances for both MyClass Bool Int and MyClass Bool String, and it would be able to disambiguate based on what type is expected.

One of the core design tradeoffs with Haskell typeclasses is the "open world assumption". Haskell type instances are implicitly global: a specific type (or sequence of types, in this case) can only have one instance in the whole program, which is implicitly exported to all the modules using that type.

This makes it really easy to get new instances of some class without realizing it, so the Haskell typechecker assumes that instances could possibly exist for any valid combination of types. In your case, this means that while MyClass Bool Int is the only instance using Bool, it's still ambiguous with other possible MyClass Bool b instances.

Once you add an annotation for the type of the whole expression, it stops being ambiguous because both a and b are fixed.

To get the behavior you expect, you can use FunctionalDependencies. These allow you to specify that there is only one possible b for any given a, which will let GHC infer the type correctly. It would look something like this:

class MyClass a b | a -> b where

Of course, this does intentionally throw out some flexibility: now you can't have instances for both MyClass Bool Int and MyClass Bool String.


Need Your Help

JQuery fadeTo()

javascript jquery html css

I got this code so far:

Jquery Click Event Is Larger Than Button

javascript jquery html css ruby-on-rails

I'm having some issues with the Jquery click event. The event is firing when I click the button but it also will fire when I click to the side of the button which produces an undesirable affect in ...

Error starting uWSGI modular build: No such file or directory - /etc/uwsgi/ext/uwsgi/uwsgi.ruby

python ruby debian uwsgi

I've install uWSGI, and I'm trying to start it in emperor mode. I've installed all the necessary dependencies, and the python plugin. The error is correct, there is no file by that name in that loc...

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.