Haskell ad hoc polymorphism

≯℡__Kan透↙ 提交于 2019-12-05 12:23:30

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.

Tikhon Jelvis elaborated the problem and proposed to use functional dependencies, but there is an alternative: type families. Your code becomes

{-# LANGUAGE TypeFamilies #-}

class MyClass a where
    type R a
    foo :: a -> R a

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

instance MyClass Double where
    type R Double = Double
    foo x = -x

We use associated type synonyms here. I like these explicit type level functions, but if you don't, it's OK to use fundeps, because differences are rather subtle.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!