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 [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
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 <[hidden email]> wrote: Hi _______________________________________________ Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
In reply to this post by Larry Lee
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 | [hidden email] _______________________________________________ Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
In reply to this post by Larry Lee
Larry Lee <[hidden email]> writes:
> 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 _______________________________________________ Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
In reply to this post by Larry Lee
Larry, By your definitionf x = x {-# 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) On Tue, Nov 11, 2014 at 10:59 PM, Larry Lee <[hidden email]> wrote: Hi _______________________________________________ Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
In reply to this post by Larry Lee
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 <[hidden email]> wrote: Hi _______________________________________________ Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
In reply to this post by Larry Lee
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 <[hidden email]>: Hi _______________________________________________ Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
In reply to this post by Larry Lee
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 <[hidden email]> wrote: Hi _______________________________________________ Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
In reply to this post by Larry Lee
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 _______________________________________________ Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
In reply to this post by Larry Lee
On 12 November 2014 07:59, Larry Lee <[hidden email]> 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 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 > [hidden email] > http://www.haskell.org/mailman/listinfo/haskell-cafe -- Ivan Lazar Miljenovic [hidden email] http://IvanMiljenovic.wordpress.com _______________________________________________ Haskell-Cafe mailing list [hidden email] http://www.haskell.org/mailman/listinfo/haskell-cafe |
Free forum by Nabble | Edit this page |