Dear Cafe, I can write and use the following, data IntHolder = IntHolder Integer instance Show IntHolder where show (IntHolder n) = show n liftInt :: (Integer -> Integer) -> IntHolder -> IntHolder liftInt f (IntHolder c) = IntHolder (f c) But I cannot generalise it to *Num:* data NumHolder = forall a. Num a => NumHolder a instance Show NumHolder where show (NumHolder n) = show n liftNum :: (Num a) => (a -> a) -> NumHolder -> NumHolder liftNum f (NumHolder c) = NumHolder (f c) The error message I get is the following: Couldn't match expected type `a' against inferred type `a1' `a' is a rigid type variable bound by the type signature for `liftNum' at Lifts.hs:54:16 `a1' is a rigid type variable bound by the constructor `NumHolder' at Lifts.hs:55:11 In the first argument of `f', namely `c' In the first argument of `NumHolder', namely `(f c)' In the expression: NumHolder (f c) Regards, -- Ozgur Akgun
Ozgur Akgun wrote:
data NumHolder = forall a. Num a => NumHolder a
instance Show NumHolder where show (NumHolder n) = show n
liftNum :: (Num a) => (a -> a) -> NumHolder -> NumHolder liftNum f (NumHolder c) = NumHolder (f c)
The problem here is that you declare that liftNum will work for any single type a, decided (effectively) by the caller of the function. But if the caller chooses Int for a, and your NumHolder has a Float inside it, that isn't going to work. You need to take a function that will work for any Num type a: liftNum :: (forall a. Num a => a -> a) -> NumHolder -> NumHolder liftNum f (NumHolder c) = NumHolder (f c) This uses Rank2Types, but that's necessary for what you want. By moving the forall from being implicit at the start of the signature to inside the brackets, you declare that this is a function that works for all types a (that are a member of type-class Num). This should compile and work as you wanted. Neil.
Aside from Neil's point about rank-2 polymorphism, you can of course just parameterise your NumHolder type... data Num a => NumHolder a = NumHolder a instance Show a => Show NumHolder a where show (NumHolder x) = show x instance Functor NumHolder where fmap f (NumHolder a) = NumHolder (f a) It depends what you want to do with your NumHolder though. What is the purpose of this type? Bob On Fri, Jan 22, 2010 at 11:31 AM, Ozgur Akgun <ozgurakgun@gmail.com> wrote:
Dear Cafe,
I can write and use the following,
data IntHolder = IntHolder Integer
instance Show IntHolder where show (IntHolder n) = show n
liftInt :: (Integer -> Integer) -> IntHolder -> IntHolder liftInt f (IntHolder c) = IntHolder (f c)
But I cannot generalise it to *Num:*
data NumHolder = forall a. Num a => NumHolder a
instance Show NumHolder where show (NumHolder n) = show n
liftNum :: (Num a) => (a -> a) -> NumHolder -> NumHolder liftNum f (NumHolder c) = NumHolder (f c)
The error message I get is the following:
Couldn't match expected type `a' against inferred type `a1' `a' is a rigid type variable bound by the type signature for `liftNum' at Lifts.hs:54:16 `a1' is a rigid type variable bound by the constructor `NumHolder' at Lifts.hs:55:11 In the first argument of `f', namely `c' In the first argument of `NumHolder', namely `(f c)' In the expression: NumHolder (f c)
Regards,
-- Ozgur Akgun
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
OK, I wasn't storing a simple (Num a) in my holder data structure, it was more of a thing implementing one of my type classes. So it knows how to quack, and I can use it now, thanks to Neil's suggestion. I have a (somewhat) heterogeneus list of values, belonging to the same type class, and I just wanted to map a function to that list. Now it works. BTW Tom, Thanks for your suggestion, but it simply doesn't fit my needs this time. But I'll keep your suggestion in mind. Cheers guys! 2010/1/22 Tom Davie <tom.davie@gmail.com>
Aside from Neil's point about rank-2 polymorphism, you can of course just parameterise your NumHolder type...
data Num a => NumHolder a = NumHolder a
instance Show a => Show NumHolder a where show (NumHolder x) = show x
instance Functor NumHolder where fmap f (NumHolder a) = NumHolder (f a)
It depends what you want to do with your NumHolder though. What is the purpose of this type?
Bob
On Fri, Jan 22, 2010 at 11:31 AM, Ozgur Akgun <ozgurakgun@gmail.com>wrote:
Dear Cafe,
I can write and use the following,
data IntHolder = IntHolder Integer
instance Show IntHolder where show (IntHolder n) = show n
liftInt :: (Integer -> Integer) -> IntHolder -> IntHolder liftInt f (IntHolder c) = IntHolder (f c)
But I cannot generalise it to *Num:*
data NumHolder = forall a. Num a => NumHolder a
instance Show NumHolder where show (NumHolder n) = show n
liftNum :: (Num a) => (a -> a) -> NumHolder -> NumHolder liftNum f (NumHolder c) = NumHolder (f c)
The error message I get is the following:
Couldn't match expected type `a' against inferred type `a1' `a' is a rigid type variable bound by the type signature for `liftNum' at Lifts.hs:54:16 `a1' is a rigid type variable bound by the constructor `NumHolder' at Lifts.hs:55:11 In the first argument of `f', namely `c' In the first argument of `NumHolder', namely `(f c)' In the expression: NumHolder (f c)
Regards,
-- Ozgur Akgun
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
-- Ozgur Akgun
participants (3)
-
Neil Brown -
Ozgur Akgun -
Tom Davie