Class/Instance : what am I doing wrong in this example ?

I'm really inexperienced at this : ----------- {-# OPTIONS_GHC -fglasgow-exts -funbox-strict-fields -fallow-undecidable-instances -O2 #-} class Gadget g where fInit :: g -> a -> g data FString = FString !Int !String deriving Show instance Gadget FString where fInit (FString n _) s = FString n (take n s) ------------- I get the error message : Couldn't match expected type `String' against inferred type `a' `a' is a rigid type variable bound by the type signature for `fInit' at Gadget.hs:4:17 In the second argument of `FString', namely `s' In the expression: FString n s In the definition of `fInit': fInit (FString n _) s = FString n s

david48 wrote: | I'm really inexperienced at this :
class Gadget g where fInit :: g -> a -> g
data FString = FString !Int !String deriving Show
instance Gadget FString where fInit (FString n _) s = FString n (take n s)
The types of:
fInit :: g -> a -> g
and:
take :: Int -> [a] -> [a]
cause the mismatched types error. You're trying to apply 'take n' to a value of type 'a' ('take n' requires [a]), moreover putting the value of 'take n s' into the FString further constrains its type to be [Char] == String. So either fix the Gadget g class, or fix the Gadget FString instance. Claude -- http://claudiusmaximus.goto10.org

On Dec 20, 2007 5:03 PM, Claude Heiland-Allen
You're trying to apply 'take n' to a value of type 'a' ('take n' requires [a]), moreover putting the value of 'take n s' into the FString further constrains its type to be [Char] == String.
First of all, thanks a lot for your reply. I thought that in this case my type a was String ( which I know is [Char] ) since I give fInit a value of type g ( FString n _ ) and a value of type a ( s ) and I return a value of type g ( FString n (take n s) ) David

david48 wrote:
class Gadget g where fInit :: g -> a -> g
data FString = FString !Int !String deriving Show
instance Gadget FString where
at this point fInit has this type: FString -> a -> FString
fInit (FString n _) s = FString n (take n s)
but your implementation has this type FString -> String -> FString These types are incompatible, your fInit implementation should be able to work with whatever type a the caller has choosen to provide. Maybe you should try one of class Gadget g where fInit :: g -> String -> g or class Gadget g a where fInit :: g -> a -> g instead. Tillmann

Tillmann Rendel wrote:
david48 wrote:
class Gadget g where fInit :: g -> a -> g
Tillman's two suggestions (below) are probably your answer. Just to say what everyone else has said in a bunch of different ways: your class says that for ANY Gadget, fInit will work with ANY OTHER type a. This doesn't seem to be what you want. There are three things you might want: 1. Maybe you want a to always be String. Easy. fInit :: g -> String -> g 2. Maybe you want lots of possible different "a"s for each "g". Then you make "a" a parameter of the class too. 3. Maybe you want just one particular "a" for each "g". I.e. "g" determines "a". Then you can proceed as for (2), but add the functional dependency | g -> a
These types are incompatible, your fInit implementation should be able to work with whatever type a the caller has choosen to provide. Maybe you should try one of
class Gadget g where fInit :: g -> String -> g
or
class Gadget g a where fInit :: g -> a -> g

On Dec 20, 2007 5:36 PM, Jules Bean
2. Maybe you want lots of possible different "a"s for each "g". Then you make "a" a parameter of the class too.
3. Maybe you want just one particular "a" for each "g". I.e. "g" determines "a". Then you can proceed as for (2), but add the functional dependency | g -> a
Practically, what would be the difference between 2. and 3. ? David.

On Dec 20, 2007 5:26 PM, Tillmann Rendel
at this point fInit has this type: FString -> a -> FString
fInit (FString n _) s = FString n (take n s) but your implementation has this type FString -> String -> FString These types are incompatible, your fInit implementation should be able to work with whatever type a the caller has choosen to provide. Maybe
That was a very clear explanation of what's wrong, thanks a lot !
you should try one of
class Gadget g where fInit :: g -> String -> g
This will not do, I want instances of gadget that work with other values than string.
or class Gadget g a where fInit :: g -> a -> g
A bit of explanation. I want types of class "Gadget" to be able to hold values of some type. for example, some of the types in the class Gadget would hold strings, some would hold Integers. With a variable of a type belonging to the class Gadget, I want to be able to - Initialise it - Fetch the value it holds - Have the user input the value - Display the value To keep it simple, in this example I only kept the funtion to initialise. So it seems I have to use the multiparameter class version, but I'm stuck here as well : class Gadget g a where fInit :: g -> a -> g data FString = FString !Int !String deriving Show instance Gadget FString String where fInit (FString n _) s = FString n (take n s) fString :: Int -> FString fString n = FString n "" ---------------------- *Main> :r [1 of 1] Compiling Main ( Gadget.hs, interpreted ) Ok, modules loaded: Main. *Main> fString 5 "" <interactive>:1:0: Couldn't match expected type `[Char] -> t' against inferred type `FString' In the expression: fString 5 "" In the definition of `it': it = fString 5 "" *Main>
participants (4)
-
Claude Heiland-Allen
-
david48
-
Jules Bean
-
Tillmann Rendel