[Haskell-cafe] A Very Simple Type Class Question
Ivan Lazar Miljenovic
ivan.miljenovic at gmail.com
Tue Nov 11 23:46:23 UTC 2014
On 12 November 2014 07:59, Larry Lee <llee454 at gmail.com> wrote:
> I have a very simple problem.
> I have a class and want to define a function in that class that returns a
> different instance of the same class.
> I tried accomplishing this as follows:
> class A a where
> f :: A b => a -> b
This type signature says "I can convert my instance of type `a' to any
instance of this type class `b'... as chosen by the *caller* of this
i.e. if you have instances for Foo, Bar and Baz, then "f Foo" isn't
fixed to just Bar: the caller can choose any instance it likes (which
is usually not what you want).
> This fails however when I try to instantiate it. For example:
> instance A String where
> f x = x
This instance only works if the `b' in the type signature of `f' is
also String, rather than being chosen by the caller.
> I get an error message that makes absolutely no sense to me:
> Could not deduce (b ~ [Char])
> from the context (A b)
> bound by the type signature for f :: A b => String -> b
> at src/CSVTree.hs:12:3-9
> `b' is a rigid type variable bound by
> the type signature for f :: A b => String -> b
> at src/CSVTree.hs:12:3
> In the expression: x
> In an equation for `f': f x = x
> In the instance declaration for `A String'
> make: *** [compile] Error 1
This is saying "The instance definition requires the `b' type to be
[Char] (i.e. String), but there's no requirement/ability in the
definition of the type to have such a constraint/requirement."
> Can someone please explain: how I can achieve my goal; and why my code is
> failing; simply and in plain English.
Depending on what exactly you want, there are three options:
* If you want each type to convert to itself, then change the type of
`f' to be just "a -> a"
* If you want a one-to-many mapping (i.e. given `a', I know there's
precisely one possible value of `b'), then use either Multi-Param Type
Classes (MPTCs) + Functional Dependencies or else an associated Type
Family alias within the type class to denote that relationship.
* If you have a many-to-many relationship (Foo can convert to Foo or
Baz, Bar can convert only to Baz and Baz can convert to anything),
then use an MPTC (though this will in general require an instance for
every possible pairing).
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
Ivan Lazar Miljenovic
Ivan.Miljenovic at gmail.com
More information about the Haskell-Cafe