Reputation: 15
i need to define an instance for the class Enum based on the datatype Int'. I just need to define the functions toEnum and fromEnum. For example: map fromEnum [Minus One .. Plus (Succ’ One)] -> [-1,0,1,2]
data PosNat = One | Succ' PosNat
data Int' = Zero' | Plus PosNat | Minus PosNat
instance Enum Int' where
toEnum 0 = Zero'
toEnum n | n>0 = Plus (toPosNat n )
toEnum n | n<0 = undefined -- Minus (toPosNat n)
where
toPosNat :: a -> PosNat
toPosNat 1 = One
toPosNat n | n>1 = (Succ' (toPosNat (n-1)) )
toPosNat n | n<1 = (Succ' (toPosNat (n+1)) )
The problem is, i get following error:
Variable not in scope: toPosNat :: Int -> PosNat
|
62 | toEnum n | n>0 = Plus (toPosNat n )
|
Thanks for your help! :)
Upvotes: 0
Views: 235
Reputation: 91837
A where
clause attaches to all of the guards of a single pattern. You've defined your function using three separate patterns, so the where
clause only attaches to the last of them. To fix this, simply roll the last two patterns (which are the same, minus the guards) together:
instance Enum Int' where
toEnum 0 = Zero'
toEnum n | n>0 = Plus (toPosNat n )
| n<0 = Minus (toPosNat n)
where
toPosNat :: a -> PosNat
toPosNat 1 = One
toPosNat n | n>1 = (Succ' (toPosNat (n-1)))
| n<1 = (Succ' (toPosNat (n+1)))
I've made the same change to toPosNat
because this is better style, but it has no semantic impact in this case.
Upvotes: 4
Reputation: 33033
You need to promote toPosNat
to a top-level function, like this:
instance Enum Int' where
toEnum 0 = Zero'
toEnum n | n>0 = Plus (toPosNat n )
toEnum n | n<0 = undefined -- Minus (toPosNat n)
toPosNat :: a -> PosNat
toPosNat 1 = One
toPosNat n | n>1 = (Succ' (toPosNat (n-1)) )
toPosNat n | n<1 = (Succ' (toPosNat (n+1)) )
The where
clause that you have in your code is only visible in the third case, not in the second case.
Upvotes: 2