Haskell: type classes: multiple inheritance example - haskell

I came to know that we can achieve multiple inheritance using type classes. I had written small haskell code, but unable to figure out the problem.
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE StandaloneDeriving #-}
class (Eq a, Show a) => C a where
getHashCode :: a -> Integer
getHashCode obj = 123
type Id = Int
type Name = String
data Employee = Employee Id Name deriving C
When i tried to load above code, I am getting following error. Any help on this.
No instance for (Eq Employee)
arising from the 'deriving' clause of a data type declaration
Possible fix:
use a standalone 'deriving instance' declaration,
so you can specify the instance context yourself
When deriving the instance for (C Employee)
Failed, modules loaded: none.
I searched google some time, but unable to found good example for multiple inheritance. it will be helpful if you provide some info, example on multiple inheritance in Haskell.
Reference: https://www.haskell.org/tutorial/classes.html

Saying
class (Eq a, Show a) => C a where
does not mean that types that implement C automatically implement Eq and Show, it means that they must first implement Eq and Show before they can implement C.
A class in Haskell is not the same as a class in Java, either, it's closer to an interface, but it can't be used in the same ways (and shouldn't). Haskell doesn't actually have a concept of inheritance or classes in the OOP sense, as it's not an OOP language.
However, if you want to have Eq and Show instances automatically for a type, just add them to the deriving clause of the data type.

Related

Typeclass resolution in Haskell reporting ambiguity even if there is only one instance

I am experimenting with transitive typeclass instances in Haskell. It is well-known that one cannot declare a transitive instance in the original typeclass (i.e. (C a b, C b c) => C a c). Therefore I tried to define another class representing the transitive closure of the original class instead. Minimal code is as below:
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
module Ambig where
class Coe a b where
from :: a -> b
class CoeTrans a b where
from' :: a -> b
instance CoeTrans a a where
from' = id
instance (Coe a b, CoeTrans b c) => CoeTrans a c where
from' = from' . from #a #b
instance Coe Bool Int where
from False = 0
from True = 1
instance Coe Int Integer where
from x = toInteger x
where CoeTrans is the transitive closure of Coe. When I'm trying to use from' in CoeTrans, however, it always reports ambiguity:
-- >>> from' True :: Integer
-- Ambiguous type variable ‘b0’ arising from a use of ‘from'’
-- prevents the constraint ‘(Coe Bool b0)’ from being solved.
-- Probable fix: use a type annotation to specify what ‘b0’ should be.
-- These potential instance exist:
-- instance Coe Bool Int
-- -- Defined at /Users/t/Desktop/aqn/src/Ambig.hs:21:10
Even if there is virtually only one instance. But according to GHC docs a typeclass resolution will succeed iff there is one applicable instance.
Why would this happen and is there any way to solve the transitive instance problem?
I think you misunderstood the docs a bit. They really say that a typeclass resolution for a given type will succeed iff one instance is present. But in your case, no type is given. b0 is ambiguous.
The compiler needs to know b0 before it can pick an instance of Coe Bool b0, even though there is only one in the current scope. And this is done this way on purpose. And the key words there are "current scope". You see, if the compiler could just pick whatever is available in scope, your program would be vulnerable to subtle changes in scope: you may change your imports, or some of your imported modules may change their internal structure. This may result in different instances appearing or disappearing in your current scope, which may result in different behaviour of your program without any kind of warning.
If you really intend for there to always be at most one unambiguous path between any two types, you can solve it by adding a functional dependency to Coe:
class Coe a b | a -> b where
from :: a -> b
This will have two effects:
The compiler will know that it can always deduce b just by knowing a.
And to facilitate that, the compiler will prohibit multiple instances with same a, but different bs from being defined.
Now the compiler can see that, since the argument of from' is Bool, it must search for an instance of Coe Bool b for some b, and from there it will know for sure what b has to be, and from there it can search for the next instance, and so on.
If, on the other hand, you really intended for there to be multiple possible paths between two given types, and for the compiler to just pick one - you're out of luck. The compiler refuses on principle` to randomly pick one of multiple possibilities - see explanation above.

"class TypeClassName a b where" is incorrect syntax?

I am learning Haskell and I am not quite sure whether class TypeClassName a b where is incorrect.
Does it make sense to write something like that in Haskell?
I know that class TypeClassName a where is correct but I am not sure whether the extra b would make any sense there ?
You can do that with Multi-parameter type class extension enabled.
{-# LANGUAGE MultiParamTypeClasses #-}
Regarding it's usage and requirement, it actually depends upon your application. For example, in the linked tutorial for type family they actually have to use this extension. Also, this wikibook section explains how it is used for Collection type class. For Collection typeclass, multi parameter type class makes good use case:
{-# LANGUAGE MultiParamTypeClasses #-}
class Eq e => Collection c e where
insert :: c -> e -> c
member :: c -> e -> Bool
Here c is the collection type like List and e is the element inside the collection. So any collection which supports insert and memebership test function can be made instance of this typeclass.

how to write a derivable class?

i have this
data Something = Something Integer deriving (MyClass, Show)
class MyClass a where
hello :: MyClass a => a -> a
instance MyClass Integer where
hello i = i + 1
main = print . hello $ Something 3
but MyClass isn't derivable. Why?
GHC cannot magically derive instances for arbitrary data types. However, it
can make use of the fact that newtype declarations create a new name for the
same underlying type to derive instances for those using the
GeneralizedNewtypeDeriving extension. So, you could do something like this:
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
newtype Something = Something Integer deriving (MyClass, Show)
class MyClass a where
hello :: MyClass a => a -> a
instance MyClass Integer where
hello i = i + 1
main = print . hello $ Something 3
The reason GHC cannot derive the new instance is that it does not know what the instance
should be. Even if your data type only has one field, it may not necessarily be the
same as that field. The ability to derive instances for newtypes is convenient, since they
are usually used to provide different behaviours for certain typeclasses or as a way to
use the type system to separate things that have the same type but different uses in your code.
You may want to have a look at the GHC documentation on Generic Programming.
You need to create a class that can work on a generic representation of arbitrary types. I don't think the specific example you gave is reasonable for a derivable class.

Predicate with forall quantifier in haskell?

I want to write the function which accepts values of types, which has instances of multiparameter type class together with every type. Something like this (signature of test function is illegal):
class Test a b
test :: forall a. (forall b. Test a b) => a -> a
Is there a way to express such restriction?
Depending on what you're trying to achieve, there may be a better solution.
But what you're asking is also possible, using the constraints package.
{-# LANGUAGE FlexibleContexts, ConstraintKinds, MultiParamTypeClasses #-}
import Data.Constraint.Forall
class Test a b
test :: Forall (Test a) => a -> a
test = undefined

How do I write, "if typeclass a, then a is also an instance of b by this definition."

I have a typeclass MyClass, and there is a function in it which produces a String. I want to use this to imply an instance of Show, so that I can pass types implementing MyClass to show. So far I have,
class MyClass a where
someFunc :: a -> a
myShow :: a -> String
instance MyClass a => Show a where
show a = myShow a
which gives the error Constraint is no smaller than the instance head. I also tried,
class MyClass a where
someFunc :: a -> a
myShow :: a -> String
instance Show (MyClass a) where
show a = myShow a
which gives the error, ClassMyClass' used as a type`.
How can I correctly express this relationship in Haskell?
Thanks.
I should add that I wish to follow this up with specific instances of MyClass that emit specific strings based on their type. For example,
data Foo = Foo
data Bar = Bar
instance MyClass Foo where
myShow a = "foo"
instance MyClass Bar where
myShow a = "bar"
main = do
print Foo
print Bar
I wish to vigorously disagree with the broken solutions posed thus far.
instance MyClass a => Show a where
show a = myShow a
Due to the way that instance resolution works, this is a very dangerous instance to have running around!
Instance resolution proceeds by effectively pattern matching on the right hand side of each instance's =>, completely without regard to what is on the left of the =>.
When none of those instances overlap, this is a beautiful thing. However, what you are saying here is "Here is a rule you should use for EVERY Show instance. When asked for a show instance for any type, you'll need an instance of MyClass, so go get that, and here is the implementation." -- once the compiler has committed to the choice of using your instance, (just by virtue of the fact that 'a' unifies with everything) it has no chance to fall back and use any other instances!
If you turn on {-# LANGUAGE OverlappingInstances, IncoherentInstances #-}, etc. to make it compile, you will get not-so-subtle failures when you go to write modules that import the module that provides this definition and need to use any other Show instance. Ultimately you'll be able to get this code to compile with enough extensions, but it sadly will not do what you think it should do!
If you think about it given:
instance MyClass a => Show a where
show = myShow
instance HisClass a => Show a where
show = hisShow
which should the compiler pick?
Your module may only define one of these, but end user code will import a bunch of modules, not just yours. Also, if another module defines
instance Show HisDataTypeThatHasNeverHeardOfMyClass
the compiler would be well within its rights to ignore his instance and try to use yours.
The right answer, sadly, is to do two things.
For each individual instance of MyClass you can define a corresponding instance of Show with the very mechanical definition
instance MyClass Foo where ...
instance Show Foo where
show = myShow
This is fairly unfortunate, but works well when there are only a few instances of MyClass under consideration.
When you have a large number of instances, the way to avoid code-duplication (for when the class is considerably more complicated than show) is to define.
newtype WrappedMyClass a = WrapMyClass { unwrapMyClass :: a }
instance MyClass a => Show (WrappedMyClass a) where
show (WrapMyClass a) = myShow a
This provides the newtype as a vehicle for instance dispatch. and then
instance Foo a => Show (WrappedFoo a) where ...
instance Bar a => Show (WrappedBar a) where ...
is unambiguous, because the type 'patterns' for WrappedFoo a and WrappedBar a are disjoint.
There are a number of examples of this idiom running around in the the base package.
In Control.Applicative there are definitions for WrappedMonad and WrappedArrow for this very reason.
Ideally you'd be able to say:
instance Monad t => Applicative t where
pure = return
(<*>) = ap
but effectively what this instance is saying is that every Applicative should be derived by first finding an instance for Monad, and then dispatching to it. So while it would have the intention of saying that every Monad is Applicative (by the way the implication-like => reads) what it actually says is that every Applicative is a Monad, because having an instance head 't' matches any type. In many ways, the syntax for 'instance' and 'class' definitions is backwards.
(Edit: leaving the body for posterity, but jump to the end for the real solution)
In the declaration instance MyClass a => Show a, let's examine the error "Constraint is no smaller than the instance head." The constraint is the type class constraint to the left of '=>', in this case MyClass a. The "instance head" is everything after the class you're writing an instance for, in this case a (to the right of Show). One of the type inference rules in GHC requires that the constraint have fewer constructors and variables than the head. This is part of what are called the 'Paterson Conditions'. These exist as a guarantee that type checking terminates.
In this case, the constraint is exactly the same as the head, i.e. a, so it fails this test. You can remove the Paterson condition checks by enabling UndecidableInstances, most likely with the {-# LANGUAGE UndecidableInstances #-} pragma.
In this case, you're essentially using your class MyClass as a typeclass synonym for the Show class. Creating class synonyms like this is one of the canonical uses for the UndecidableInstances extension, so you can safely use it here.
'Undecidable' means that GHC can't prove typechecking will terminate. Although it sounds dangerous, the worst that can happen from enabling UndecidableInstances is that the compiler will loop, eventually terminating after exhausting the stack. If it compiles, then obviously typechecking terminated, so there are no problems. The dangerous extension is IncoherentInstances, which is as bad as it sounds.
Edit: another problem made possible by this approach arises from this situation:
instance MyClass a => Show a where
data MyFoo = MyFoo ... deriving (Show)
instance MyClass MyFoo where
Now there are two instances of Show for MyFoo, the one from the deriving clause and the one for MyClass instances. The compiler can't decide which to use, so it will bail out with an error message. If you're trying to make MyClass instances of types you don't control that already have Show instances, you'll have to use newtypes to hide the already-existing Show instances. Even types without MyClass instances will still conflict because the definition instance MyClass => Show a because the definition actually provides an implementation for all possible a (the context check comes in later; its not involved with instance selection)
So that's the error message and how UndecidableInstances makes it go away. Unfortunately it's a lot of trouble to use in actual code, for reasons Edward Kmett explains. The original impetus was to avoid specifying a Show constraint when there's already a MyClass constraint. Given that, what I would do is just use myShow from MyClass instead of show. You won't need the Show constraint at all.
I think it would be better to do it the other way around:
class Show a => MyClass a where
someFunc :: a -> a
myShow :: MyClass a => a -> String
myShow = show
You can compile it, but not with Haskell 98, You have to enable some language extensions :
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
-- at the top of your file
Flexible instances is there to allow context in instance declaration. I don't really know the meaning of UndecidableInstances, but I would avoid as much as I can.
As Ed Kmett pointed out, this is not possible at all for your case. If however you have access to the class you want to provide a default instance for, you can reduce the boilerplate to a minimum with a default implementation and constrain the input type with the default signature you need:
{-# LANGUAGE DefaultSignatures #-}
class MyClass a where
someFunc :: a -> Int
class MyShow a where
myShow :: a -> String
default myShow :: MyClass a => a -> String
myShow = show . someFunc
instance MyClass Int where
someFunc i = i
instance MyShow Int
main = putStrLn (myShow 5)
Note that the only real boilerplate (well, apart from the whole example) reduced to instance MyShow Int.
See aesons ToJSON for a more realistic example.
You may find some interesting answers in a related SO question: Linking/Combining Type Classes in Haskell

Resources