[Haskell-cafe] Smart Constructor Puzzle
Ronald Guida
ronguida at mindspring.com
Thu Dec 20 23:39:42 EST 2007
I'm playing around with smart constructors, and I have encountered a
weird puzzle.
My goal is to do vector arithmetic. I'm using smart constructors so
that I can store a vector as a list and use the type system to
staticly enforce the length of a vector.
So my first step is to define Peano numbers at the type level.
> data PZero = PZero deriving (Show)
> data PSucc a = PSucc a deriving (Show)
>
> type P1 = PSucc PZero
> type P2 = PSucc P1
> type P3 = PSucc P2
> -- etc
Next, I define a vector type and tag it with a Peano number.
> data Vec s t = Vec [t] deriving (Eq, Ord, Show, Read)
Now I can define a few smart constructors.
> vec0 :: Vec PZero t
> vec0 = Vec []
>
> vec1 :: t -> Vec P1 t
> vec1 x = Vec [x]
>
> vec2 :: t -> t -> Vec P2 t
> vec2 x y = Vec [x, y]
>
> vec3 :: t -> t -> t -> Vec P3 t
> vec3 x y z = Vec [x, y, z]
Now here's the puzzle. I want to create a function "vecLength" that
accepts a vector and returns its length. The catch is that I want to
calculate the length based on the /type/ of the vector, without
looking at the number of elements in the list.
So I started by defining a class that allows me to convert a Peano
number to an integer. I couldn't figure out how to define a function
that converts the type directly to an integer, so I am using a
two-step process. Given a Peano type /t/, I would use the expression
"pToInt (pGetValue :: t)".
> class Peano t where
> pGetValue :: t
> pToInt :: t -> Int
>
> instance Peano PZero where
> pGetValue = PZero
> pToInt _ = 0
>
> instance (Peano t) => Peano (PSucc t) where
> pGetValue = PSucc pGetValue
> pToInt (PSucc a) = 1 + pToInt a
Finally, I tried to define vecLength, but I am getting an error.
> vecLength :: (Peano s) => Vec s t -> Int
> vecLength _ = pToInt (pGetValue :: s)
< Could not deduce (Peano s1) from the context ()
< arising from a use of `pGetValue'
< Possible fix:
< add (Peano s1) to the context of the polymorphic type `forall s. s'
< In the first argument of `pToInt', namely `(pGetValue :: s)'
< In the expression: pToInt (pGetValue :: s)
< In the definition of `vecLength':
< vecLength _ = pToInt (pGetValue :: s)
Any suggestions?
-- Ron
More information about the Haskell-Cafe
mailing list