
John, This is one MAJOR hurdle for newcomers to get over and pretty much everyone stumbles and falls into typed combinator enlightenment. Eventually. Let's ask ghci what some of the types are: :t [1,2,3] [1,2,3] :: [Int] :t (+7) (+7) :: Int -> Int :t (<$>) (<$>) :: Functor f => (a -> b) -> f a -> f b So in ((+7) <$>) we have (<$>) :: Functor f => (a -> b) -> f a -> f b applied to (note the _type_ of the first argument: a -> b): (+7) :: Int -> Int Now the type variables a and b must match up, so we have a=b=Int. And now we have ((+7) <$>) :: Functor f => f Int - f Int Which is, in turn, applied to [1,2,3] :: [Int] The argument in ((+7) <$>) has type Functor f => f Int, whereas [1,2,3] is [Int], so what can f be? Answer: []. Yes, [] is a functor, the way Maybe and IO are functors. So f = []. It's unusual but only syntatically in the sense that Haskell says to write Maybe Int but rejects [] Int. You have to write [Int] to mean [] Int. We say that ((+7) <$>) :: Functor f => f Int - f Int is thus specialized to ((+7) <$>) :: [Int] -> [Int] which is why (+7) <$> [1,2,3] typechecks and runs as it should. If you run through the above against the rest of the list of things that do and don't work, I think you'll sew up typed combinators as a fine feather in your cap. Just remember that [] is a Functor and also an Applicative and a Monad. Trying different combinations is so much more satisfying if you lean on the types to lead you to greater good. -- Kim-Ee