Related
Reading Function application with $ in Learn You Haskell book I found example of applying $ to list of functions.
map ($ 3) [(4+), (10*), (^2), sqrt]
I wanted try similar thing and reduce example to applying to one function
fmap ($ 3) (4+)
But I am getting errors which I don't understand
• Non type-variable argument in the constraint: Num (a -> b)
(Use FlexibleContexts to permit this)
• When checking the inferred type
it :: forall a b. (Num (a -> b), Num a) => (a -> b) -> b
Could you help me understand why it works in the first case but it doesn't in the second? How can I achieve desired effect?
Thank you
You need map in the first example because you have a whole container full of functions, and each of them you want to apply to the number. In that example, you could indeed also replace map with fmap, which does work on any container (on any functor).
Prelude> fmap ($ 3) [(4+), (10*), (^2), sqrt] -- list functor
[7.0,30.0,9.0,1.7320508075688772]
Prelude> fmap ($ 3) (Just (4+)) -- `Maybe` functor
Just 7
Prelude> fmap ($ 3) (do y<-readLn; return (y+)) -- `IO` functor
> 100
103
However, (4+) by itself is not a function wrapped in any functor, it's just a function by itself. So, you don't really need any fmap:
Prelude> ($ 3) (4+)
7
Of course you could simplify that even further to 4+3...
If for some reason you do need to use fmap regardless†, you'd need it to operate in the identity functor:
Prelude> :m +Data.Functor.Identity
Prelude Data.Functor.Identity> fmap ($ 3) (Identity (4+))
Identity 7
The identity functor is a very boring container that just always contains exactly one element.
†That's not unrealistic BTW: in Haskell we like to keep code as generic as possible. You may have a function that is able to work with arbitrary functors (more typically, arbitrary monads, which are special functors) but may want to use it in the trivial context of just one element contained. Or, you may want to stack different monad functionalities as monad transformers; then you'll generally start with Identity as the “vanilla monad”.
I would say the main issue is that your (4 +) is not wrapped correctly inside a functor. If you inspect the type of fmap you'll get:
Prelude> :t fmap
fmap :: Functor f => (a -> b) -> f a -> f b
In your first example, all the functions were wrapped in a list. Here if you change your (4 +) into [ (4 +) ], it will work.
As for the explanation about functor, you'll probably find more documentation online (or in the comment section :D Thanks for the feedback)
fmap applies a function to values found in some functorial value. In fmap ($ 3) [(4+), (10*), (^2), sqrt], the list is the functorial value, and the function ($ 3) is applied to its elements. As for fmap ($ 3) (4+), leftaroundabout correctly points out that:
However, (4+) by itself is not a function wrapped in any functor, it's just a function by itself.
In this case, there is a complementary way to look at it. (4+) is a functorial value; however, the functor isn't the one you need. Functions are functors, and, for the purposes of fmap, the values "found in them" are the results of the function:
GHCi> :set -XTypeApplications
GHCi> :t fmap #((->) _)
fmap #((->) _) :: (a -> b) -> (w -> a) -> w -> b
fmap for functions applies a function to the results of another function, which amounts to function composition. So this...
GHCi> fmap (4*) (2+) 1
12
... is the same as:
GHCi> ((4*) . (2+)) 1
12
In your case, we have:
GHCi> :t (4+)
(4+) :: Num a => a -> a
So fmap f (4+) will apply f to the Num a => a result of (4+). The type of ($ 3), though, is:
GHCi> :t ($ 3)
($ 3) :: Num a => (a -> b) -> b
And so fmap ($ 3) will expect a functorial value with functions to be possibly found in it:
GHCi> :t fmap ($ 3)
fmap ($ 3) :: (Num a, Functor f) => f (a -> b) -> f b
Putting it all together, we get:
GHCi> :t fmap ($ 3) (4+)
fmap ($ 3) (4+) :: (Num (a -> b), Num a) => (a -> b) -> b
The type error this will lead to has to do with the Num (a -> b) constraint. If there are functions to be found in (4+), then 4 itself must be a function. As 4 is a numeric literal, its type must be also an instance of Num. However, there is no Num instance for functions. Trying fmap ($ 3) (4+) leads to an error which mentions Num (a -> b). That should suggest something is off:
GHCi> fmap ($ 3) (4+)
<interactive>:33:1: error:
* Non type-variable argument in the constraint: Num (a -> b)
(Use FlexibleContexts to permit this)
* When checking the inferred type
it :: forall a b. (Num (a -> b), Num a) => (a -> b) -> b
The "Non-type variable argument" complaint, though, is a bit of a distraction, induced by numeric literals being polymorphic. We can get a more straightforward error either by enabling FlexibleContexts and then trying to use fmap ($ 3) (4+) (which will lead to Num a => a being specialised to Integer thanks to the defaulting rules)...
GHCi> :set -XFlexibleContexts
GHCi> fmap ($ 3) (4+) (2*)
<interactive>:39:1: error:
* No instance for (Num (Integer -> Integer))
arising from a use of `it'
(maybe you haven't applied a function to enough arguments?)
* In the first argument of `print', namely `it'
In a stmt of an interactive GHCi command: print it
... or by specialising the numeric type through a type annotation:
GHCi> fmap ($ 3) ((4 :: Integer)+)
<interactive>:42:13: error:
* Couldn't match type `Integer' with `Integer -> b'
Expected type: Integer -> Integer -> b
Actual type: Integer -> Integer
* In the second argument of `fmap', namely `((4 :: Integer) +)'
In the expression: fmap ($ 3) ((4 :: Integer) +)
In an equation for `it': it = fmap ($ 3) ((4 :: Integer) +)
* Relevant bindings include
it :: Integer -> b (bound at <interactive>:42:1)
Is there any explanation for why a lifted function, when applied to 2-tuple, only applies to the 2nd entry:
f x = x + 1
f <$> (2,2)
// -> (2,3)
On the other hand, tuples of any other length than 2 return errors.
Also
:t f <$>
returns an error. Is it possible to see the type of f <$> when acting on tuples?
Is there any explanation for that behaviour?
The Data.Tuple documentation is extremely brief and has no mention of how functions are lifted to tuples. Is there any source explaining it?
Update. A part of question about 2-tuples is related to this answer, where, however, the above question about multiple length tuples is not addressed.
One could (and arguably, GHC should) define a Functor instance for triples and larger tuples. To wit:
instance Functor ((,,) a b) where
fmap f (a, b, c) = (a, b, f c)
If this instance truly doesn't exist anywhere in base, I suspect that's mostly oversight, though I don't know the history well enough to say for sure. You can include this in any code where it seems useful, with the caveat that you should then absolutely put a fairly strict upper bound on the version of base in your *.cabal file, as this instance might reasonably be included in future versions of base. The PVP allows only the third component of the version to change in such a case, so include at least that many components in your upper bound!
Is there any explanation for why a lifted function, when applied to 2-tuple, only applies to the 2nd entry
Because tuples are heterogeneous which means that, in general, it would not make sense to try to apply a function of type b -> c to each component of a tuple of type (a, b).
If you want pairs of values of the same type, you can declare your own type Pair and then have the functor instance apply the function to each component.
data Pair a = Pair { fst :: a
, snd :: a }
instance Functor Pair where
fmap f (Pair fst snd) = Pair (f fst) (f snd)
Is it possible to see the type of f <$> when acting on tuples?
f <$> is a section (a partially applied infix operator). To get its type, you need to wrap it with parentheses like so:
:t (f <$>)
The Data.Tuple documentation is extremely brief and has no mention of how functions are lifted to tuples. Is there any source explaining it?
The combinator (<$>) (and (<*>)) are more general than just for tuples, you can find them in the Control.Applicative module.
All the other answers here seem pretty good, but I don't think anyone precisely answered your question yet.
I believe the reason 2-tuples (and no other tuples) are treated this way by default is because this allows them to be used in the same way as a Writer in a monadic context. (That is, ((,) a) and Writer are isomorphic.)
For example, given a function running in a Writer monad:
import Control.Monad.Writer
foo :: Int -> Writer [String] Int
foo n = do tell ["Running foo " ++ show n]
if (n <= 0) then do
tell ["We are done!"]
return 1
else do
rest <- foo (n-1)
return (n * rest)
you can rewrite it using the Monad instance of ((,) a):
bar :: Int -> ([String], Int)
bar n = do tell' ["Running bar " ++ show n]
if (n <= 0) then do
tell' ["We are done!"]
return 1
else do
rest <- bar (n-1)
return (n * rest)
where tell' str = (str, ())
and you'll find that these do the same thing:
runWriter (foo 5)
bar 5
up to the ordering of the pair.
The definition of tell' is only needed because ((,) a) hasn't been made an instance of MonadWriter for some reason.
(Edited to add:) While you could extend the definition to larger tuples, this doesn't really provide any additional generality over the definition for the pair: one component of the pair is a monoid to which you can write, and the other component is the underlying "value" in the monad context -- if you need more components for one or the other, you can just make the component a tuple itself.
In this answer, I will just expand a bit on one of the suggestions I made in a comment.
Is it possible to see the type of f <$> when acting on tuples?
(<$>) is a polymorphic function:
GHCi> :t (<$>)
(<$>) :: Functor f => (a -> b) -> f a -> f b
With GHC 8, you can use the TypeApplications extension to specialise polymorphic functions by supplying instantiations of some or all of their type variables (in this case, f, a and b, in that order):
GHCi> :set -XTypeApplications
GHCi> :t (<$>) #Maybe
(<$>) #Maybe :: (a -> b) -> Maybe a -> Maybe b
GHCi> :t (<$>) #Maybe #Int
(<$>) #Maybe #Int :: (Int -> b) -> Maybe Int -> Maybe b
GHCi> :t (<$>) #Maybe #_ #Bool
(<$>) #Maybe #_ #Bool :: (t -> Bool) -> Maybe t -> Maybe Bool
GHCi> :t (<$>) #_ #Int #Bool
(<$>) #_ #Int #Bool
:: Functor t => (Int -> Bool) -> t Int -> t Bool
GHCi> :t (<$>) #Maybe #Int #Bool
(<$>) #Maybe #Int #Bool :: (Int -> Bool) -> Maybe Int -> Maybe Bool
To use that with pairs, use the prefix syntax for the pair type constructor:
GHCi> :t (<$>) #((,) _)
(<$>) #((,) _) :: (a -> b) -> (t, a) -> (t, b)
GHCi> -- You can use the specialised function normally.
GHCi> -- That includes passing arguments to it.
GHCi> f x = x + 1
GHCi> :t (<$>) #((,) _) f
(<$>) #((,) _) f :: Num b => (t, b) -> (t, b)
The _ in ((,) _) leaves it unspecified what the type of the first element of the pair (which is the first argument of the (,) type constructor) should be. Every choice of it gives rise to a different Functor. You can be more specific if you wish:
GHCi> :t (<$>) #((,) String) f
(<$>) #((,) String) f :: Num b => (String, b) -> (String, b)
Lastly, it is worth having a look at what happens if you try that with 3-tuples:
GHCi> :t (<$>) #((,,) _ _) f
(<$>) #((,,) _ _) f
:: (Num b, Functor ((,,) t t1)) => (t, t1, b) -> (t, t1, b)
As Daniel Wagner discusses in his answer, base doesn't define a Functor instance for 3-tuples. In spite of that, the type checker cannot exclude the possibility that someone somewhere might have defined an instance specific for some choice of the first two type parameters, however pointless that would be. For that reason, the speculative constraint Functor ((,,) t t1) shows up in the type (no such thing happens with pairs because there is a Functor ((,) a) instance in base). As expected, that blows up as soon as we try to instantiate the first two type parameters:
GHCi> :t (<$>) #((,,) Bool String) f
<interactive>:1:1: error:
• Could not deduce (Functor ((,,) Bool String))
arising from a use of ‘<$>’
from the context: Num b
bound by the inferred type of
it :: Num b => (Bool, String, b) -> (Bool, String, b)
at <interactive>:1:1
• In the expression: (<$>) #((,,) Bool String) f
I'm looking at the following function:
fmap :: (a -> b) -> f a -> f b
and I want to understand what the 'f' is, as in (f a or f b). The article I am reading describes it as a 'box' but what's the actual correct name for it? Is it just a type variable? I think I'm confusing it and thinking it's a function application - which is correct?
Your intuition that it is a kind of function application is correct, but they are not regular functions. Instead, this is application of type constructors on the type level.
Specifically, Functors must have kind (type-of-type) * -> * which means they take one type argument and produce a concrete type * such as, for example, [Int].
Examples of such type constructors include IO, Maybe, [], Either e and many others, and these specific examples all have valid Functor instances.
fmap (+1) [1,2,3] :: [] Int -- also known as [Int]
= [2,3,4]
fmap (+1) (Just 1) :: Maybe Int
= Just 2
fmap (+1) (Right 1) :: Either e Int
= Right 2
fmap (+1) (return 1) :: IO Int -- Uses Monad IO instance as well
"=" 2
It's a type variable, representing the particular functor you're working in. For example IO is a functor, so you can specialize fmap to
fmap :: (a -> b) -> IO a -> IO b
Similarly you could specialize it to lists:
fmap :: (a -> b) -> [a] -> [b]
Currently reading through this article (which is pretty brilliant btw) and have a pretty simple question:
If I combine two functions like (+3) and (+2) with <$>, it seems to give me a new function that adds 5 to whatever is passed to it. If I do the same with the function composition operator, i.e. (+3) . (+2), would it not do the same thing? If that is true, is there a relationship here between these two operators such that they do the same thing in this simple case?
Is this even an intelligent question?
The functions fmap and <$> both have the same type:
> :t fmap
fmap :: Functor f => (a -> b) -> f a -> f b
> :t (<$>)
(<$>) :: Functor f => (a -> b) -> f a -> f b
While the function . is
> :t (.)
(.) :: (b -> c) -> (a -> b) -> a -> c
So how is it possible that we can use fmap on a function and end up with .? I'm assuming you understand what a Functor is, so now you have to understand that "functions" are Functors. How so?
> :i (->)
data (->) a b -- Defined in `GHC.Prim'
instance Monad ((->) r) -- Defined in `GHC.Base'
instance Functor ((->) r) -- Defined in `GHC.Base'
instance Applicative ((->) a) -- Defined in `Control.Applicative'
Unlike Just, [] and Left, functions do not have a constructor that can be used. The Functor instance is applied to the syntax itself. We can see from :info in ghci that the syntactic arrow -> actually has an instance for functor.
What happens when we look at the type of +3?
> :t (+3)
(+3) :: Num a => a -> a
So the function (+3) is a Functor that accepts an a and returns an a. When we use fmap on a Functor and that also gives us back a Functor, we get nested Functors:
> :t fmap Just (Just 3)
fmap Just (Just 3) :: Num a => Maybe (Maybe a)
> :t fmap (replicate 5) [1,2,3]
fmap (replicate 5) [1,2,3] :: Num a => [[a]]
Likewise, when we apply fmap to two functions we get a function inside a function. The only difference is that they are fused together:
> :t (fmap (+3) (+2))
(fmap (+3) (+2)) :: Num a => a -> a
Why doesn't this result in the type (->) (->) a a? We have to remember that the first argument of fmap is a function (a -> b) and not necessarily a Functor. So when we do fmap g (Just 5) we can have any transformation. But whenever we perform fmap on a function we know that it will always result with a function inside of a function.
Thus fmap (+3) (+2) evaluates to something like this: \x -> (\x' -> x' + 3) (x + 2). That is a really roundabout way of writing (+3) . (+2).
> :t (fmap (+3) (+2))
(fmap (+3) (+2)) :: Num a => a -> a
> :t ((.) (+3) (+2))
((.) (+3) (+2)) :: Num a => a -> a
Normally to get around the concat problem (Maybe (Maybe a)) or [[a]] we actually need to rely on it being a Monad a, so that we can use a bind >>=. But functions (->) are a special case because we know that every single time we use fmap on a function, it will always give us a function in side of a function. This cannot be said for any other Functor except ->. As such we can be sure to always concatenate fmap on functions.
Therefore any f <$> g == f . g
Edit: A quick side note, if you do this fmap (+) (+0) you end up with a function inside a function. In this case the monadic bind (>>=) is actually needed to concatenate the functions:
> :t fmap (+) (+0)
fmap (+) (+0) :: Num a => a -> a -> a
> :t (+0) >>= (+)
(+0) >>= (+) :: Num b => b -> b
> let bindfunc = (+0) >>= (+)
> bindfunc 5
10
Which is not entirely unlike the behaviour we get when we do [1,2] >>= replicate 5:
> [1,2] >>= replicate 5
[1,1,1,1,1,2,2,2,2,2]
To find information about the Functor instance for functions, match up the types to find the relevant instance:
fmap :: (a -> b) -> f a -> f b
Then here a ~ Int, b ~ Int and f ~ (->) Int.
You can see all of the Functor instances that come with GHC here. (->) is just an infix type operator with two type parameters. We usually see it applied as Int -> Int, but this is equivalent to (->) Int Int.
There is a Functor instance for the (partially applied) type (->) r (for any type r::*).
Looking at the ((->) r) instance for Functor, we see that fmap = (.), so there is no practical difference between (+3) . (+2) and fmap (+3) (+2) (same as (+3) <$> (+2).
Here are some pragmas and some imports:
{-# LANGUAGE ScopedTypeVariables #-}
import Control.Monad.ST
import Data.Array.ST
import Data.Array
Now here's my problem. The following code typechecks:
foo :: forall a. a -> [a]
foo x = elems $ runSTArray $ do
newListArray (1,10) (replicate 10 x) :: ST s (STArray s Int a)
However, when I replace the $ with composition:
foo :: forall a. a -> [a]
foo x = elems . runSTArray $ do
newListArray (1,10) (replicate 10 x) :: ST s (STArray s Int a)
I get this error:
Couldn't match expected type `forall s. ST s (STArray s i0 e0)'
with actual type `ST s0 (STArray s0 Int a)'
In the expression:
newListArray (1, 10) (replicate 10 x) :: ST s (STArray s Int a)
In the second argument of `($)', namely
`do { newListArray (1, 10) (replicate 10 x) ::
ST s (STArray s Int a) }'
In the expression:
elems . runSTArray
$ do { newListArray (1, 10) (replicate 10 x) ::
ST s (STArray s Int a) }
What's werid is, if I give the function composition its own name, then it typechecks again:
elemSTArray = elems . runSTArray
foo :: forall a. a -> [a]
foo x = elemSTArray $ do
newListArray (1,10) (replicate 10 x) :: ST s (STArray s Int a)
I'm not sure what's going on here. I would expect the second piece of code to typecheck nicely. And I don't understand why it typechecks again if I give the composed function its own name.
This is a simplified version of some code that I had that broke when upgrading from GHC 6.2 to 7 and I'm trying to understand why this happens now. Thanks for helping!
As you already hint at in the title of your post, the problem has to do with runSTArray having a polymorphic type of rank 2.
runSTArray :: Ix i => (forall s. ST s (STArray s i e)) -> Array i e
With
elems :: Ix i => Array i e -> [e]
and
($) :: (a -> b) -> a -> b
writing runSTArray $ ... means that the type variable a in the type schema of ($) needs to be instantiated with a polymorphic type rather than a monomorphic type. This requires so-called impredicative polymorphism. How GHC implements impredicative polymorphism is explained in the ICFP 2008 paper by Dimitrios Vytiniotis, Stephanie Weirich, and Simon Peyton Jones: FPH : First-class Polymorphism for Haskell. The bottom line is that while FPH often gives you the behaviour that you expect, typeability is sometimes not preserved under simple transformations like the ones you describe in your question: see Section 6.2 of the aforementioned paper.
Stefan beat me to the answer -- the tricky bit is that it's not the $ vs . between elems and runSTArray that's the issue -- it's the $ following runSTArray. Since something $ rankNthing is so common, there's a clever bit (I forget the details) that tries to let you do that as a corner case. But somehow using the composition earlier on prevents this. The location of the issue is demonstrated by the fact that the following will typecheck:
foo x = (elems . runSTArray) (
(newListArray (1,10) (replicate 10 x) :: ST s (STArray s Int String)))
I'm not sure this is a bug per se, but its certainly an unexpected behavior worth creating a ticket about, since there might still be a better algorithm to catch cases like the one you provided.