[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