Joe Susnick
Joe Susnick

Reputation: 6772

Why does the Maybe type wrap its value in a list?

I'm going through learnyouahaskell, great book, and I'm at the chapter on typeclasses. Here's the question. In GHCi when I enter

fmap (++ "String to be appended to") ("I am a basic string, not a type constructor")

I get the error

Couldn't match type ‘Char’ with ‘[Char]’
Expected type: [[Char]]
  Actual type: [Char]
In the second argument of ‘fmap’, namely
  ‘("I am a basic string, not a type constructor")’

I understand why I'm getting this error (because a functor requires a type constructor with a value like Just "I am a value being passed to the Maybe type constructor" but I don't understand why the error reads expected type [[Char]] is the Maybe type actually wrapping the value in a list? What's the deal?

Upvotes: 0

Views: 221

Answers (2)

ErikR
ErikR

Reputation: 52057

Your code will work if you simply add a Just:

fmap (++ "xyz") (Just "another string")

results in: Just "another stringxyz"

Upvotes: 0

phadej
phadej

Reputation: 12133

List [] is a functor too. GHC unifies fmap to be on lists, and deduces from the first argument that its type is fmap :: (String -> String) -> [String] -> String:

λ Prelude > :t (fmap :: (String -> String) -> [String] -> [String]) (++ "String to be appended to")  ("I am a basic string, not a type constructor")

<interactive>:1:88:
    Couldn't match type ‘Char’ with ‘[Char]’
    Expected type: [String]
    Actual type: [Char]

But you probably expect fmap to be specialised to fmap :: (String -> String) -> Maybe String -> Maybe String, which would give a different error message:

λ Prelude > (fmap :: (String -> String) -> Maybe String -> Maybe String) (++ "String to be appended to")  ("I am a basic string, not a type constructor")

<interactive>:11:96:
    Couldn't match expected type ‘Maybe String’
                with actual type ‘[Char]’
    In the second argument of ‘fmap ::
                                 (String -> String) -> Maybe String -> Maybe String’, namely
      ‘("I am a basic string, not a type constructor")’

Sometimes GHC doesn't get our intentions, and finds the "wrong" cause of our error.

Upvotes: 6

Related Questions