Вопрос

Please see this newly written code now, there is no "read" used, and still I get error on ambiguous "show":

data MyType0 a = Tong1 a | Tong2 a  deriving Show
data MyType1 a = Cons1 a | Cons2 a | Cons3 | Cons4 deriving Show
data MyType2 a = MyType2 a deriving Show

fun ((Cons2 s):t:ts) (symseq, MyType2 msg) = (symseq, MyType2 (msg ++ ["You provided wrong symbol: " ++ (show t) ++ " Please provide symbol: " ++ (show Cons3) ]))
--fun ((Cons2 s):t:ts) (symseq, MyType2 msg) = (symseq, MyType2 (msg ++ ["You provided wrong symbol: " ++ (show t) ++ " Please provide symbol: " ]))
fun _ syms                                  = syms

The ghci error msg:

showerr.hs:6:148:
    Ambiguous type variable `a0' in the constraint:
      (Show a0) arising from a use of `show'
    Probable fix: add a type signature that fixes these type variable(s)
    In the second argument of `(++)', namely `(show Cons3)'
    In the second argument of `(++)', namely
      `" Please provide symbol: " ++ (show Cons3)'
    In the second argument of `(++)', namely
      `(show t) ++ " Please provide symbol: " ++ (show Cons3)'
Failed, modules loaded: none.

note that the commented part doesn't give this error. please explain why this is so error.

original message is kept below.

I got the following code on a site. I know ambiguous type error can come for the "read" function but here i get it for the "show" function too. i find it strange and not understand.

code:

main = do run <- getLine
          val <- getLine
          case run of
              "len" -> print . show . len $ (read val)
              "rev" -> print . show . rev $ (read val)
              _ -> putStr "wrong option"

rev :: [a] -> [a]
rev = foldl (flip (:)) []

len :: [a] -> Int
len = foldl (\ac _ -> ac + 1) 0

When i load it in ghci i get error.

ideone_x0cMx.hs:4:46:
    Ambiguous type variable `a0' in the constraint:
      (Read a0) arising from a use of `read'
    Probable fix: add a type signature that fixes these type variable(s)
    In the second argument of `($)', namely `(read val)'
    In the expression: print . show . len $ (read val)
    In a case alternative: "len" -> print . show . len $ (read val)

ideone_x0cMx.hs:5:46:
    Ambiguous type variable `a1' in the constraints:
      (Read a1) arising from a use of `read' at ideone_x0cMx.hs:5:46-49
      (Show a1) arising from a use of `show' at ideone_x0cMx.hs:5:32-35
    Probable fix: add a type signature that fixes these type variable(s)
    In the second argument of `($)', namely `(read val)'
    In the expression: print . show . rev $ (read val)
    In a case alternative: "rev" -> print . show . rev $ (read val)
Failed, modules loaded: none.
Это было полезно?

Решение

In the subexpression (show Cons3), there is no context to determine the type parameter of MyType1.

Cons3 is a constructor for any MyType1 a, and calling show on it restricts a to an instance of Show, but beyond that, nothing can be inferred. So the type variable is ambiguous, and since there is no numeric constraint, it cannot be defaulted (unless you enable ExtendedDefaultRules).

The type variable could be fixed if you write

show (Cons3 `asTypeOf` t)

or - for example -

show (Cons3 :: MyType1 String)

there.

Другие советы

Answer to first question:

Your ambiguity does come from the read function!

If you use type-specific versions of len and rev, it'll work. For example, you could replace len with (len :: [Int] -> Int) or replace (read val) with (read val :: [Int])


Answer to second question:

Cons3 :: MyType1 a

so Haskell doesn't know what the type a is. You could specify explicitly (and it doesn't matter what you choose if you're just showing it):

fun ((Cons2 s):t:ts) (symseq, MyType2 msg) = 
    (symseq, MyType2 (msg ++ ["You provided wrong symbol: " ++ (show t) 
       ++ " Please provide symbol: " ++ show (Cons3 :: MyType Int) ]))

Normally it can deduce the type of Cons3 from context, but you create one from the literal and show it straight away, so there isn't a context.

What type should read val be? Your code says that it should be a list (because rev and len both accept all types of list), but doesn't say what it should be a list of.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top