A Very Simple Type Class Question

Hi 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 fails however when I try to instantiate it. For example: instance A String where f x = x I get an error message that makes absolutely no sense to me: src/CSVTree.hs:12:9: 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 Can someone please explain: how I can achieve my goal; and why my code is failing; simply and in plain English. Thanks, Larry

When you declare a type signature such as
f :: C x => a -> b
there is an implicit "forall":
f :: forall x. C x => a -> x
That is, the type signature must hold *for all* x such that C x holds.
However, in your case, it only holds for String – while A String does hold,
that is irrelevant, because the type signature states that it must hold for
*any* x such that A x that the caller wants. To put it another way, the
caller decides the "b" in that type signature, not the function
implementation.
What you want is something like
f :: exists x. C x => a -> x
so that f will return some unknown value such that you know it is an
instance of C x.
Hope that helps,
Andrew
On Tue, Nov 11, 2014 at 12:59 PM, Larry Lee
Hi
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 fails however when I try to instantiate it. For example:
instance A String where f x = x
I get an error message that makes absolutely no sense to me:
src/CSVTree.hs:12:9: 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
Can someone please explain: how I can achieve my goal; and why my code is failing; simply and in plain English.
Thanks, Larry _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Hi Larry, On 11/11/2014 09:59 PM, Larry Lee wrote:
Hi
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 fails however when I try to instantiate it. For example:
instance A String where f x = x
I get an error message that makes absolutely no sense to me:
f has type (A a, A b) => a -> b. Both a and b can be thosen by the caller. If you try to create an instance of A like you did, this will not type check, as you have only provided a function of type String -> String, whereas a function of type A b => String -> b (for *all* b) is required. I hope that clears things up a little. Thanks, Jochem -- Jochem Berndsen | jochem@functor.nl

Larry Lee
Hi
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
The only possible implementation for function f will be const undefined. Your function f promises that given a value of type a, it can return a value of *any* type b, as long as b is an instance of typeclass A. So, once we are given a value of type a, we have to produce a value of type b, however, we don't know what type b is! The only thing that we know about things of type b is that they are an instance of A. This is not enough information to be able to produce something of type b.
This fails however when I try to instantiate it. For example:
instance A String where f x = x
I get an error message that makes absolutely no sense to me:
src/CSVTree.hs:12:9: Could not deduce (b ~ [Char]) from the context (A b) <snip>
See the above: you are producing of type String. However, according to the type signature, you should be able to produce something of an arbitrary type b. Clearly that is not possible. I am guessing that once you know the type a, you also know what the output type b will be. If that is the case then you can use type families: class A a where type B a f :: a -> B a instance A String where type B String = String f = id Hope this helps. Regards, -- - Frank

Larry,
By your definition
f x = x
this function returns whatever it got in it's argument, thus:
1. compiler infers that it's argument is of type String from
class-definition
2. String is actually a type-synonim for list of chars
type String = [Char]
3. So now, on one hand function is returning something of a concrete type
[Char], and on the other (from class-definition) it should be some type
only restricted by operations on type-class.
Regarding your question on "how to do things properly" -- I'm not sure what
exactly are you trying to achieve. Could you describe a problem you're
trying to solve?
If you want to return something of type b, which is only constrainted by
being an instance of a type-class A, then you need to create it with a
function defined in class A. But since only function is f, it's not enough.
Here's an example of solution for the original "return something of another
instance" problem:
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeSynonymInstances #-}
class A a where
f :: A b => a -> b
def :: a
instance A Int where
f x = def
def = 4
instance A String where
f x = def
def = "asd"
main :: IO ()
main = print $ (f "asd" :: Int)
Cheers.
On Tue, Nov 11, 2014 at 10:59 PM, Larry Lee
Hi
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 fails however when I try to instantiate it. For example:
instance A String where f x = x
I get an error message that makes absolutely no sense to me:
src/CSVTree.hs:12:9: 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
Can someone please explain: how I can achieve my goal; and why my code is failing; simply and in plain English.
Thanks, Larry _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

First, there is an even simpler case that won't work:
class A a where
foo :: a -> b
The question is what is 'b'. According to this b can be anything not
something specific. If you want 'b' to be something specific in must appear
as part of the type class declaration.
To do what you want to do, you could use the extension
MultiParamTypeClasses.
class A a
class (A a, A b) => B a b where
foo :: a -> b
instance A Int
instance B Int Int where
foo = id
Second, Haskell does not by default allow for type synonyms in instance
declarations. String is a type synonym of [Char]. If you want to use String
in instance declarations use the extension TypeSynonymInstances and
FlexibleInstances.
instance A String
instance A String String where
foo = id
James
On Tue, Nov 11, 2014 at 12:59 PM, Larry Lee
Hi
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 fails however when I try to instantiate it. For example:
instance A String where f x = x
I get an error message that makes absolutely no sense to me:
src/CSVTree.hs:12:9: 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
Can someone please explain: how I can achieve my goal; and why my code is failing; simply and in plain English.
Thanks, Larry _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

The problem is that the type of f is
f :: (A a, A b) => a -> b
This means that given an 'a', you need to create a function which works for
*any* b in A.
However, the function you implement is of type `f :: String -> String`, not
of type `f :: A b => String -> b`, as needed. If you were to implement the
function in that way, you could use:
class A a where
f :: a -> a
2014-11-11 21:59 GMT+01:00 Larry Lee
Hi
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 fails however when I try to instantiate it. For example:
instance A String where f x = x
I get an error message that makes absolutely no sense to me:
src/CSVTree.hs:12:9: 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
Can someone please explain: how I can achieve my goal; and why my code is failing; simply and in plain English.
Thanks, Larry _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

The caller of your function f, rather than the implementation of f, gets to
decide which instance of A f should return. In other words, f's
implementation must be polymorphic in its return type. Your example f
x = x does
not satisfy that property. That implementation has type f :: A a => a -> a,
not the required type f :: (A a, A b) => a -> b.
The error message is saying that, from the class definition, GHC has
deduced that f must return a value of type A b => b, but your
implementation is returning a String (a.k.a. [Char]) instead. The notation b
~ [Char] means "b is equivalent to [Char]".
On Tue, Nov 11, 2014 at 12:59 PM, Larry Lee
Hi
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 fails however when I try to instantiate it. For example:
instance A String where f x = x
I get an error message that makes absolutely no sense to me:
src/CSVTree.hs:12:9: 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
Can someone please explain: how I can achieve my goal; and why my code is failing; simply and in plain English.
Thanks, Larry _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On Tue, Nov 11, 2014 at 03:59:50PM -0500, Larry Lee 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 fails however when I try to instantiate it. For example:
instance A String where f x = x
The `f` that you defined has type `String -> String`. However, given the definition of the class `A` it should have been of type `A b => String -> b`. What exactly are you trying to do here? This is probably not the way to go about it. Tom

On 12 November 2014 07:59, Larry Lee
Hi
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 function". 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:
src/CSVTree.hs:12:9: 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).
Thanks, Larry _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
-- Ivan Lazar Miljenovic Ivan.Miljenovic@gmail.com http://IvanMiljenovic.wordpress.com
participants (10)
-
Alejandro Serrano Mena
-
Andrew Gibiansky
-
Frank Staals
-
Ivan Lazar Miljenovic
-
James M
-
Jochem Berndsen
-
Konstantine Rybnikov
-
Larry Lee
-
Taylor Hedberg
-
Tom Ellis