Apologies, I dabble in Haskell in a minor way, once ever 2 years, and then I can't get my head around it.
Its best to just do the example.
> {-# LANGUAGE MultiParamTypeClasses #-}
> {-# LANGUAGE ScopedTypeVariables #-}
> {-# LANGUAGE AllowAmbiguousTypes #-}
> {-# LANGUAGE FlexibleInstances #-}
> {-# LANGUAGE FlexibleContexts #-}
> class Foo a b where
> foo :: a -> b
>
> class Bar a b where
> bar :: a -> b
> data A a = A a
> data B b = B b
> instance Foo (A a) a where
> foo (A a) = a
> instance Bar (B b) b where
> bar (B b) = b
so, what I THINK I'm doing is create to data types and then defining two functions based on the the membership of the datatype in the class....
so this works....
> f1 x = foo x
> f2 x = bar x
> x1 :: String
> x1 = f1 $ A "1"
> x2 :: String
> x2 = f2 $ B "1"
simple...
worry #1...if I remove the type declaration of x1 and x2, ghc complains
• Ambiguous type variable ‘b1’ arising from a use of ‘f1’
prevents the constraint ‘(Foo (A [Char]) b1)’ from being solved.
Relevant bindings include x1 :: b1 (bound at catdog.lhs:27:3)
Probable fix: use a type annotation to specify what ‘b1’ should be.
These potential instance exist:
instance Foo (A a) a -- Defined at catdog.lhs:17:12
• In the expression: f1 $ A "1"
In an equation for ‘x1’: x1 = f1 $ A "1"
|
27 | > x1 = f1 $ A "1" | ^^^^^^^^^^
which is a worry, isnt it obvious?...and this sort of thing will happen again.....
if I write
> f x = bar (foo x)
to me a perfectly reasonable thing...ghc agrees!
I ask it for the type...I get
f :: (Bar a1 b, Foo a2 a1) => a2 -> b
I can buy that.
like a good programmer I paste the type in
> f :: (Bar a1 b, Foo a2 a1) => a2 -> b
> f x = bar (foo x)
and "BOOM"...
• Could not deduce (Foo a2 a0) arising from a use of ‘foo’
from the context: (Bar a1 b, Foo a2 a1)
bound by the type signature for:
f :: forall a1 b a2. (Bar a1 b, Foo a2 a1) => a2 -> b
at catdog.lhs:32:3-39
The type variable ‘a0’ is ambiguous
Relevant bindings include
x :: a2 (bound at catdog.lhs:33:5)
f :: a2 -> b (bound at catdog.lhs:33:3)
These potential instance exist:
instance Foo (A a) a -- Defined at catdog.lhs:17:12
• In the first argument of ‘bar’, namely ‘(foo x)’
In the expression: bar (foo x)
In an equation for ‘f’: f x = bar (foo x)
|
33 | > f x = bar (foo x) | ^^^^^
so ghc is telling me the type it inferred without a type declaration, its now not sure about!
now...there is usually one cog in my head that gets turned backwards by using scala or f# or some other OO style type system, that I have to turn the other way around....am I going mad?
Foo (A String) band can't figure out whatbis. I guess it's not capable of seeing that your script has only one such instance in this case (withbbeingString) - if you had more than one then it would certainly have just cause to complain about an ambiguity. - Robin Zigmonda1is, and can't read the constraints as saying "I want there to be some typea1for which the constraintsBar a1 bandFoo a2 a1hold simultaneously". Not sure how you could set this up (or if it's possible at all) so I will leave that to others more knowledgeable. - Robin Zigmond