
Hi-- More silly typeclass questions. I'm not sure the right way to ask it, so I'll start with a failed code snippet: data Foo a = Foo a class TwoPi a where div2pi :: (Floating b) => a -> b instance (Floating a) => TwoPi (Foo a) where div2pi (Foo a) = a / (2*pi) a/(2*pi) has type Floating a => a, where a is the type of a in Foo a.
I'm still having a hard time finding a way to make this work, even given the fine suggestions from Tobias and Jürgen. I suspect there's some piece of information that the compiler can't make sense of that I'm just not seeing-- a case of it insisting on doing what I say instead of what I mean... =)
I guess the problem I'm having is finding a way to treat parametric and non-parametric types interchangeably. The syntax doesn't seem to exist that will allow me to say:
div2pi :: (Floating a) => a -> a -- for non parametric types (ie. Float)
and
div2pi :: (Floating b) => a b -> b -- for parametric types (ie. Foo Float)
In addition, I'm having a hard time understanding the errors I'm getting from constructs like this:
data Foo a = Foo a
class TwoPi a where
div2pi :: (Floating b) => a -> b
instance (Floating a) => TwoPi (Foo a) where
div2pi (Foo x) = x / (2*pi)
{- only this code, no other instances in the file -}
It complains that I can't match expected b against inferred a where
`b' is a rigid type variable bound by
the type signature for `div2pi' at gcbTest.hs:6:22
which points immediately before the 'b' in (Floating b) of the div2pi type statement, and
`a' is a rigid type variable bound by
the instance declaration at gcbTest.hs:8:19
which points immediately before the 'a' in the (Floating a) of the instance definition. It sounds like it's saying there's an explicit conflict between two type variables, both constrained identically. Is the problem instead that they aren't well enough constrained? It wants to know what instance of the Floating class to expect? I would hope that it wouldn't care whether I provided Foo Float or Foo Double, and would return whatever type it received.
Here's the full error:
Couldn't match expected type `b' against inferred type `a'
`b' is a rigid type variable bound by
the type signature for `div2pi' at gcbTest.hs:6:22
`a' is a rigid type variable bound by
the instance declaration at gcbTest.hs:8:19
In the expression: x / (2 * pi)
In the definition of `div2pi': div2pi (Foo x) = x / (2 * pi)
In the instance declaration for `TwoPi (Foo a)'
Thanks--
Greg
On Aug 27, 2010, at 02:31 AM, Jürgen Doser
instance TwoPi Float where div2pi a = a / (2*pi) a/(2*pi) has type Float (because a has type Float), so this again can not work.
You would need a function f::(Floating b) => Float -> b for this to work. In the former, you would need a function f::(Floating a, Floating b) => a -> b.
This code is obviously meaningless, but I'm trying to figure out how you can create instances of a typeclass for data types of different kinds. I have a similar piece of code that works: data Foo a = Foo a class Testable a where isPos :: a -> Bool instance (Ord b, Num b) => Testable (Foo b) where isPos (Foo b) = b > 0 b > 0 has type Bool, no matter what type of number b is. so this is ok.
instance Testable Float where isPos a = a > 0 same here One obvious difference is that the type of isPos is a -> Bool, with a defined type as the return. I'd rather not commit to a specific Floating type up front (I'd prefer sometimes Float sometimes Double, depending on the 'a' in Foo a, but trying to declare it as Float doesn't help me. This fails: data Foo a = Foo a class TwoPi a where div2pi :: a -> Float instance (Floating b) => TwoPi (Foo b) where div2pi (Foo b) = b / (2*pi) b/(2*pi) has type Floating b => b, not Float. You would need a function of type Floating b => b -> Float.
instance TwoPi Float where div2pi a = a / (2*pi) This is ok
What is the difference between these last two cases ("a -> Bool" and "a -> Float"),
The difference is not between these type, but between (>), and (/). (>) returns Bool, no matter the type of its arguments. (/) returns sth of the same type as its arguments.
and is there anyway to make "a -> b" work?
The closest is probably using a function like: realToFrac::(Real a, Fractional b) => a -> b then you can write sth like data Foo a = Foo a class TwoPi a where div2pi :: (Floating b) => a -> b instance (Real a, Floating a) => TwoPi (Foo a) where div2pi (Foo a) = a / (2*pi) Jürgen _______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners