The following code doesnt compile:
class Foo f where
getInt :: f -> Int
class Bar b where
getFooFromBar :: Foo f => b -> f
someFunction :: Bar b => b -> Int
someFunction bar = getInt $ getFooFromBar bar
The error is Could not deduce (Foo f) arising from a use of 'getInt' from the context (Bar b)
I know I can fix the error by changing the class for Bar as follows:
class Foo f => Bar f b where
getFooFromBar :: b -> f
But I would prefer if I didnt have to add f to all the instance signatures of Bar.
Is there a way to do this by only keeping the Foo f constraint only on the getFooFromBar signature, rather than the whole class?
But I would prefer if I didnt have to add
fto all the instance signatures ofBar.
Technically speaking, you don't need to do that to make your example compile. You can use a type annotation to specify which instance of Foo you are using in someFunction, solving the ambiguous type variable error. However, you have a deeper problem:
class Foo f where
getInt :: f -> Int
class Bar b where
getFooFromBar :: Foo f => b -> f
That is, for all practical purposes, impossible. The type of getFooFromBar says you can use it to produce a result of any type f that has an instance of Foo. But how will you materialise this value for any f? It is no use reaching for any specific instance when defining getFooFromBar, as all you will get from that is a Couldn't match type ‘f’ with ‘Blah’ type error. The immediate solution to that is the one you suggested, for a different reason, in the question: specifying the instance of Foo to use through the Bar instance. You might find it nicer to do with a type family, rather than a multi-parameter type class:
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}
class Foo f where
getInt :: f -> Int
class Foo (FooBar b) => Bar b where
type FooBar b :: *
getFooFromBar :: b -> FooBar b
instance Foo Char where
getInt = const 99
instance Bar Char where
type FooBar Char = Char
getFooFromBar = const 'a'
someFunction :: Bar b => b -> Int
someFunction = getInt . getFooFromBar
GHCi> someFunction 'z'
99
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With