Partial Function Application in Haskell - haskell

I'm just starting to learn Haskell from this wikibook and I had a little trouble with one of the exercises.
Specifically, the following doesn't work as I expect
parseNumber :: Parser LispVal
parseNumber = (many1 digit) >>= (return $ Number . read)
unless I change it slightly
parseNumber :: Parser LispVal
parseNumber = (many1 digit) >>= (\n -> return $ Number . read $ n)
I was hoping someone could explain why return $ Number . read doesn't evaluate to the same lambda function that I explicitly created in the second definition, since I thought that this is exactly what partial function evaluation does when it's used in point free style code (obviously not!)
Thanks for any help, hopefully it's not another beginner’s monad problem...

This is just an issue of how $ associates. Fundamentally, $ is just an operator for writing fewer parentheses; it's the same as adding parentheses wrapping to the end of the expression.
Using this idea, we can rewrite your second example:
parseNumber = (many1 digit) >>= (\n -> return (Number . read ( n)))
For reference, the original expression with parentheses looks like this:
parseNumber = (many1 digit) >>= (return (Number . read))
So the equivalent of the partial application is actually:
parseNumber = (many1 digit) >>= (\n -> (return (Number . read)) n)
Basically, combining multiple $ associates differently than what you expected.

Go to the definitions --
($) :: (a -> b) -> a -> b
($) = id
(.) :: (b -> c) -> (a -> b) -> (a -> c)
(.) f g x = f (g x)
Now you have
return $ Number . read = ($) return (Number . read) -- (.) has higher precedence
= return (Number . read)
and the monad you're in is the Parser monad, so this is trying to bind a parsed value to a function that returns a parser for another function (many layers of abstraction!)
Instead, what you want is
return . Number . read
which is equivalent to what you wrote, as you can see by doing
\n -> return $ Number . read $ n = \n -> return . Number . read $ n -- definition of (.)
= return . Number . read -- eta reduction
Finally, note that when you see the pattern
x >>= return . f
this can always be replaced with
fmap f x -- or liftM f x
i.e. it shows that you're not really using the Monad instance at all, but instead the weaker (and more general) Functor instance.

It looks like you want:
parseNumber = (many1 digit) >>= (return . Number . read)
or alteratively
parseNumber = (many1 digit) `fmap` (Number . read)
Number . read is a function String -> LispVal so the type of return $ Number . read is Parser (String -> LispVal), while you need the function to have type String -> Parser LispVal

Related

fmap versus <$>

According to the documentation <$> is an synonym for fmap and they have the following types:
(<$>) :: Functor f => (a -> b) -> f a -> f b
fmap :: Functor f => (a -> b) -> f a -> f b
So it seems to me, from the signatures above, that they take the arguments in the same order, the only difference being that one is infix and the other is not. I have two pieces of code, one using fmap, and the other using <$>. Why is it that only the former runs correctly?
import Control.Applicative
main :: IO ()
main = do
[x, y] <- map read . words <$> getLine
putStrLn $ show (x + y)
This one won't compile:
import Control.Applicative
main :: IO ()
main = do
[x, y] <- map read . fmap words getLine
putStrLn $ show (x + y)
Precedence of operators is expressed as an integer between 0 and 9, while function application effectively has precedence 10 (higher than any operator).
(.) has very high precedence (9), while (<$>) has lower precedence (4), resulting in your first expression being parsed as
((map read) . words) <$> getLine
while your second expression is parsed as
(map read) . (fmap words getLine)
resulting in an attempt to compose an IO [String] value with a function of type [String] -> [a].
This is due to operator precedence. If we look at the source code, we see that:
infixl 4 <$>
infixr 9 .
So that means that if you write:
map read . words <$> getLine
Haskell sees this as:
(map read . words) <$> getLine
But if you write:
map read . fmap words getLine
Haskell sees this as:
(map read) . (fmap words getLine)
So the arguments of fmap are different.
If we however add brackets, the two will be equivalent:
import Control.Applicative
main :: IO ()
main = do
[x, y] <- map read . (words <$> getLine)
putStrLn $ show (x + y)

Function Composition Do Notation

Is there a "do notation" syntactic sugar for simple function composition?
(i.e. (.) :: (b -> c) -> (a -> b) -> a -> c)
I'd like to be able to store results of some compositions for later (while still continuing the chain.
I'd rather not use the RebindableSyntax extension if possible.
I'm looking for something like this:
composed :: [String] -> [String]
composed = do
fmap (++ "!!!")
maxLength <- maximum . fmap length
filter ((== maxLength) . length)
composed ["alice", "bob", "david"]
-- outputs: ["alice!!!", "david!!!"]
I'm not sure something like this is possible, since the result of the earlier function essentially has to pass "through" the bind of maxLength, but I'm open to hearing of any other similarly expressive options. Basically I need to collect information as I go through the composition in order to use it later.
Perhaps I could do something like this with a state monad?
Thanks for your help!
Edit
This sort of thing kinda works:
split :: (a -> b) -> (b -> a -> c) -> a -> c
split ab bac a = bac (ab a) a
composed :: [String] -> [String]
composed = do
fmap (++ "!!!")
split
(maximum . fmap length)
(\maxLength -> (filter ((== maxLength) . length)))
One possible way to achieve something like that are arrows. Basically, in “storing interstitial results” you're just splitting up the information flow through the composition chain. That's what the &&& (fanout) combinator does.
import Control.Arrow
composed = fmap (++ "!!!")
>>> ((. length) . (==) . maximum . fmap length &&& id)
>>> uncurry filter
This definitely isn't good human-comprehensible code though.
A state monad would seem to allow something related too, but the problem is that the state type is fixed through the do block's monadic chain. That's not really flexible enough to pick up different-typed values throughout the composition chain. While it is certainly possible to circumvent this (amongst them, indeed, RebindableSyntax), this too isn't a good idea IMO.
The type of (<*>) specialised to the function instance of Applicative is:
(<*>) :: (r -> a -> b) -> (r -> a) -> (r -> b)
The resulting r -> b function passes its argument to both the r -> a -> b and the r -> a functions, and then uses the a value produced by the r -> a function as the second argument of the r -> a -> b one.
What does this have to do with your function? filter is a function of two arguments, a predicate and a list. Now, a key aspect of what you are trying to do is that the predicate is generated from the list. That means the core of your function can be expressed in terms of (<*>):
-- Using the predicate-generating function from leftaroundabout's answer.
maxLengthOnly :: Foldable t => [t a] -> [t a]
maxLengthOnly = flip filter <*> ((. length) . (==) . maximum . fmap length)
composed :: [String] -> [String]
composed = maxLengthOnly . fmap (++ "!!!")
This maxLengthOnly definition would be a quite nice one-liner if the pointfree predicate-generating function weren't so clunky.
Since the Applicative instance of functions is equivalent in power to the Monad one, maxLengthOnly can also be phrased as:
maxLengthOnly = (. length) . (==) . maximum . fmap length >>= filter
(The split you added to your question, by the way, is (>>=) for functions.)
A different way of writing it with Applicative is:
maxLengthOnly = filter <$> ((. length) . (==) . maximum . fmap length) <*> id
It is no coincidence that this looks a lot like leftaroundabout's solution: for functions, (,) <$> f <*> g = liftA2 (,) f g = f &&& g.
Finally, it is also worth noting that, while it is tempting to replace id in the latest version of maxLengthOnly with fmap (++ "!!!"), that won't work because fmap (++ "!!!") changes the length of the strings, and therefore affects the result of the predicate. With a function that doesn't invalidate the predicate, though, it would work pretty well:
nicerComposed = filter
<$> ((. length) . (==) . maximum . fmap length) <*> fmap reverse
GHCi> nicerComposed ["alice","bob","david"]
["ecila","divad"]
As leftaroundabout mentioned, you can use Arrows to write your function. But, there is a feature in ghc Haskell compiler, which is proc-notation for Arrows. It is very similar to well-known do-notation, but, unfortunately, not many people aware of it.
With proc-notation you can write your desired function in next more redable and elegant way:
{-# LANGUAGE Arrows #-}
import Control.Arrow (returnA)
import Data.List (maximum)
composed :: [String] -> [String]
composed = proc l -> do
bangedL <- fmap (++"!!!") -< l
maxLen <- maximum . fmap length -< bangedL
returnA -< filter ((== maxLen) . length) bangedL
And this works in ghci as expected:
ghci> composed ["alice", "bob", "david"]
["alice!!!","david!!!"]
If you are interested, you can read some tutorials with nice pictures to understand what is arrow and how this powerful feature works so you can dive deeper into it:
https://www.haskell.org/arrows/index.html
https://en.wikibooks.org/wiki/Haskell/Understanding_arrows
What you have is essentially a filter, but one where the filtering function changes as you iterate over the list. I would model this not as a "forked" composition, but as a fold using the following function f :: String -> (Int, [String]):
The return value maintains the current maximum and all strings of that length.
If the first argument is shorter than the current maximum, drop it.
If the first argument is the same as the current maximum, add it to the list.
If the first argument is longer, make its length the new maximum, and replace the current output list with a new list.
Once the fold is complete, you just extract the list from the tuple.
-- Not really a suitable name anymore, but...
composed :: [String] -> [String]
composed = snd . foldr f (0, [])
where f curr (maxLen, result) = let currLen = length curr
in case compare currLen maxLen of
LT -> (maxLen, result) -- drop
EQ -> (maxLen, curr:result) -- keep
GT -> (length curr, [curr]) -- reset

Filter a list of tuples by fst

What I'm trying to do is not really solve a problem, but more to learn how to write Haskell code that composes/utilizes basic functions to do it.
I have a function that takes a list of tuples (String, Int) and a String, and returns a tuple whose fst matches the given String.
This was fairly easy to do with filter and lambda, but what I want to do now, is remove the rightmost argument, ie. I want to refactor the function to be a composition of partially applied functions that'll do the same functionality.
Original code was:
getstat :: Player -> String -> Stat
getstat p n = head $ filter (\(n', v) -> n' == n) $ stats p
New code is:
getstat :: Player -> String -> Stat
getstat p = head . (flip filter $ stats p) . cmpfst
where cmpfst = (==) . fst . (flip (,)) 0 -- Wrong :-\
The idea is to flip the filter and partially apply by giving in the list of tuples (stats p) and then compose cmpfst.
cmpfst should be String -> (String, Int) -> Bool so that when String argument is applied, it becomes a -> Bool which is good for the filter to pass in tuples, but as you can see - I have problems composing (==) so that only fst's of given tuples are compared.
P.S. I know that the first code is likely cleaner; the point of this task was not to write clean code but to learn how to solve the problem through composition.
Edit:
I understand well that asking for a head on an possibly empty list is a bad programming that'll result in a crash. Like one earlier poster mentioned, it is very simply and elegantly resolved with Maybe monad - a task I've done before and am familiar with.
What I'd like the focus to be on, is how to make cmpfst composed primarily of basic functions.
So far, the furthest I got is this:
getstat :: Player -> String -> Stat
getstat p = head . (flip filter $ stats p) . (\n' -> (==(fst n')) . fst) . (flip (,)) 0
I can't get rid of the (a -> Bool) lambda by composing and partially applying around (==). This signals, to me, that I either don't understand what I'm doing, or it's impossible using (==) operator in the way I imagined.
Furthermore, unless there's no exact solution, I'll accept signature-change solution as correct one. I'd like not to change the signature of the function simply because its a mental exercise for me, not a production code.
If I were writing this function, I'd probably have given it this type signature:
getstat :: String -> Player -> Stat
This makes it easy to eta-reduce the definition to
getstat n = head . filter ((== n) . fst) . stats
In a comment, you reached
getstat p = head . (flip filter $ stats p) . (\n (n', v) -> n' == n)
I wonder if there's a nicer composition that can eliminate the anon f.
Well, here it is
\n (n', v) -> n' == n
-- for convenience, we flip the ==
\n (n', v) -> n == n'
-- prefix notation
\n (n', v) -> (==) n n'
-- let's remove pattern matching over (n', v)
\n (n', v) -> (==) n $ fst (n', v)
\n x -> (==) n $ fst x
-- composition, eta
\n -> (==) n . fst
-- prefix
\n -> (.) ((==) n) fst
-- composition
\n -> ((.) . (==) $ n) fst
-- let's force the application to be of the form (f n (g n))
\n -> ((.) . (==) $ n) (const fst $ n)
-- exploit f <*> g = \n -> f n (g n) -- AKA the S combinator
((.) . (==)) <*> (const fst)
-- remove unneeded parentheses
(.) . (==) <*> const fst
Removing p is left as an exercise.

How do i write the following function with the >>= operator

How do I write this function using the >>= operator?
parseNumber2 :: Parser LispVal
parseNumber2 = do x <- many1 digit
return $ (Number . read) x
A straightforward desugaring of the do-notation gives
parseNumber2 :: Parser LispVal
parseNumber2 = many1 digit >>= (return . Number . read)
but the more idiomatic way is to use fmap or the equivalent <$> operator from Control.Applicative
parseNumber2 = Number . read <$> many1 digit
To desugar do-notation:
Flip any <- bindings over to the right side and add >>= and a lambda abstraction
do x <- a
y <- b
...
becomes
a >>= \x ->
b >>= \y ->
...
For any non-binding forms, add a >> on the right:
do a
b
...
becomes
a >>
b >>
...
Leave the last expression alone.
do a
becomes
a
Applying these rules to your code, we get
parseNumber2 =
many1 digit >>= \x ->
return $ (Number . read) x
Do some simplifications
parseNumber2 = many1 digit >>= \x -> (return . Number . read) x
parsenumber2 = many1 digit >>= (return . Number . read)
Now, for any monad, fmap or <$> can be defined as
f <$> x = x >>= (return . f)
Use this to get the idiomatic form
parseNumber2 = Number . read <$> many1 digit

Monadic type confusion

I am going through Write Yourself a Scheme in Haskell. Its a great tutorial, but I've run into a wall with one of the parsing exercises:
parseNumber :: Parser LispVal
parseNumber = liftM (Number . read) $ many1 digit
Rewrite parseNumber using:
Do-notation
explicit sequencing with the >>= operator
I had no problems with do-notation:
parseNumber :: Parser LispVal
parseNumber = do x <- many1 digit
let y = read x
return $ Number y
For #2 I've tried a bunch of variations such as:
parseNumber :: Parser LispVal
parseNumber = (many1 digit) >>= (liftM (Number . read))
but I keep running into type errors. I have two questions.
Why am I getting type errors? Am I misunderstanding the monadic bind operator?
Why AREN'T I getting similar type errors with my do-notation solution?
I feel like I am missing a fundamental concept regarding types?
You're attempting a non-trivial transformation from do-notation to bind notation, I recommend doing it the "trivial" way, and then making it points-free.
Recall:
x <- m === m >>= \x ->
let x = e === let x = e in
Then you have:
parseNumber = many1 digit >>= \x ->
let y = read x in
return (Number y)
(I've removed the $ to avoid precedence problems.)
We can then convert this into:
parseNumber = many1 digit >>= \x -> return (Number (read x))
= many1 digit >>= return . Number . read
Now, if you want to use liftM, you need to stop using bind, since the lifted function expects a monadic value as its argument.
parseNumber = liftM (Number . read) (many1 digit)
In your case, bind has type:
(>>=) :: Parser a -> (a -> Parser b) -> Parser b
(since you're using Parser as the Monad)
You give bind two arguments: the first one, many1 digit, should be ok (regarding the type); but the type of the second argument is the result type of liftM, namely Parser a -> Parser b and this does not fit the second argument's expected type (a -> Parser b)!
Without having tested it: instead of using liftM (Number.read) as second argument of bind, try using return . Number . read - this should have the right type and gives probably what you want...

Resources