[Haskell-beginners] instances of different kinds
Jürgen Doser
jurgen.doser at gmail.com
Fri Aug 27 05:31:38 EDT 2010
El vie, 27-08-2010 a las 01:58 -0700, Greg escribió:
> 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.
the class declaration however requires to be able to return a value of
type Floating b => b for any type b, no relation to a whatsoever.
> 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
More information about the Beginners
mailing list