
When writing a command-line interface I ran into type class conflicts I don't understand. Could anyone explain why ghc 6.10.4 compiles this
methods :: (Eq a) => [(String, a)] methods = [ ("method1", undefined ) , ("method2", undefined) ]
but not the following?
methods :: (Eq a) => [(String, a)] methods = [ ("method1", undefined ) , ("method2", undefined) ]
enumerateMethodNames :: [String] enumerateMethodNames = map fst methods
thanks, Marcus -- View this message in context: http://old.nabble.com/type-class-constraints-headache-tp27752745p27752745.ht... Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com.

methods :: (Eq a) => [(String, a)] methods = [ ("method1", undefined ) , ("method2", undefined) ]
enumerateMethodNames :: [String] enumerateMethodNames = map fst methods
The above does not compile because the source does not have enough information for GHC to determine what actual types to use for "methods" since undefined can stand in as values for any type. The program will compile if you use actual values instead of undefined or supply an explicit type signature. for example: enumerateMethodNames = map fst (methods :: [(String, String)]) or methods :: [(String, SomeEqType)] Rahul

Thanks. I realize there are many ways to make it compile.
However, I am trying to understand the mechanism behind --
why does the first example compile and what constraints does
enumerateMethodNames add on a (which it does not inspect)?
cheers,
Marcus
2010/3/4 Rahul Kapoor
methods :: (Eq a) => [(String, a)] methods = [ ("method1", undefined ) , ("method2", undefined) ]
enumerateMethodNames :: [String] enumerateMethodNames = map fst methods
The above does not compile because the source does not have enough information for GHC to determine what actual types to use for "methods" since undefined can stand in as values for any type. The program will compile if you use actual values instead of undefined or supply an explicit type signature.
for example:
enumerateMethodNames = map fst (methods :: [(String, String)]) or methods :: [(String, SomeEqType)]
Rahul

I am trying to understand the mechanism behind -- why does the first example compile and what constraints does enumerateMethodNames add on a (which it does not inspect)?
enumerateMethodNames does not add on any constraints. If you don't actually use "methods" GHC does not care what it's type is but the moment you use it some place the compiler needs to infer it's type which it is unable to do in your case because the "undefined"s can be of any type. HTH Rahul

Perhaps this thought exercise will make things clear:
class Show a => Foo a where toFoo :: String -> a
foos :: (Foo a) => [(String, a)] foos = map (\f -> (show f, f)) [toFoo "a", toFoo "b", toFoo "c"]
data Foo1 = Foo1 instance Show Foo1 where show _ = "1" instance Foo Foo1 where toFoo _ = Foo1 data Foo2 = Foo2 instance Show Foo2 where show _ = "2" instance Foo Foo2 where toFoo _ = Foo2
exercise :: [String] exercise = map fst foos
Exercise for the reader: what should the contents of "exercise" be?
Keep in mind that your question is exactly the same as this one, from
the compiler's point of view.
-- ryan
On Wed, Mar 3, 2010 at 10:48 PM, Marcus Uneson
Thanks. I realize there are many ways to make it compile. However, I am trying to understand the mechanism behind -- why does the first example compile and what constraints does enumerateMethodNames add on a (which it does not inspect)?

Thanks, it did! (For the record, here is a paraphrase of what first confused me -- undefined was not the problem).
enumerateMethodNames :: [String] enumerateMethodNames = map fst methodsNoConstr --enumerateMethodNames = map fst methodsConstr
methodsConstr :: (Ord a) => [(String, [a] -> Int)] methodsConstr = [ ("method", methodConstr )] where methodConstr :: (Ord a) => [a] -> Int methodConstr xs = length . sort $ xs
methodsNoConstr :: [(String, [a] -> Int)] methodsNoConstr = [ ("method", methodNoConstr )] where methodNoConstr :: [a] -> Int methodNoConstr = length
--First enumerateMethodNames works as expected, second does not compile.
2010/3/4 Ryan Ingram
Perhaps this thought exercise will make things clear:
class Show a => Foo a where toFoo :: String -> a
foos :: (Foo a) => [(String, a)] foos = map (\f -> (show f, f)) [toFoo "a", toFoo "b", toFoo "c"]
data Foo1 = Foo1 instance Show Foo1 where show _ = "1" instance Foo Foo1 where toFoo _ = Foo1 data Foo2 = Foo2 instance Show Foo2 where show _ = "2" instance Foo Foo2 where toFoo _ = Foo2
exercise :: [String] exercise = map fst foos
Exercise for the reader: what should the contents of "exercise" be?
Keep in mind that your question is exactly the same as this one, from the compiler's point of view.
-- ryan
On Wed, Mar 3, 2010 at 10:48 PM, Marcus Uneson
wrote: Thanks. I realize there are many ways to make it compile. However, I am trying to understand the mechanism behind -- why does the first example compile and what constraints does enumerateMethodNames add on a (which it does not inspect)?

Which "a" should it use for "methods"? On 4 Mar 2010, at 09:07, muneson wrote:
When writing a command-line interface I ran into type class conflicts I don't understand. Could anyone explain why ghc 6.10.4 compiles this
methods :: (Eq a) => [(String, a)] methods = [ ("method1", undefined ) , ("method2", undefined) ]
but not the following?
methods :: (Eq a) => [(String, a)] methods = [ ("method1", undefined ) , ("method2", undefined) ]
enumerateMethodNames :: [String] enumerateMethodNames = map fst methods
thanks,
Marcus
-- View this message in context: http://old.nabble.com/type-class-constraints-headache-tp27752745p27752745.ht... Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com.
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Related question probably: why ghc compiles this:
{-# LANGUAGE RankNTypes, ImpredicativeTypes #-} methods :: [(String, forall b. Eq b => b)] methods = [ ("method1", undefined ) , ("method2", undefined) ]
test:: [String] test= pmap methods where pmap = map fst
But when I change 'test' to:
test:: [String] test= map fst methods
I get: Cannot match a monotype with `forall b. (Eq b) => b' Expected type: [(String, b)] Inferred type: [(String, forall b1. (Eq b1) => b1)] In the second argument of `map', namely `methods' In the expression: map fst methods Failed, modules loaded: none. -- View this message in context: http://old.nabble.com/type-class-constraints-headache-tp27752745p27779518.ht... Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com.
participants (6)
-
Eduard Sergeev
-
Marcus Uneson
-
Miguel Mitrofanov
-
muneson
-
Rahul Kapoor
-
Ryan Ingram