Join two IOs with - in haskell - haskell

I need to join two IO Strings with a - in between. Here's what I came up with, which works - what's the right way?
import System.Environment
f :: String -> String -> IO String
f x y = (foldl1 (++)) <$> sequence [(getEnv x),(return "-"),(getEnv y)]

You could here use an applicative style function:
f :: String -> String -> IO String
f x y = withHyp <$> getEnv x <*> getEnv y
where withHyp ex ey = ex ++ '-' : ey
So here we join the two Strings that are then joined with a hypen in the middle through the withHyp function.
Or for a list of environment variables that we need to fetch, we can use mapM and perform an intercalate:
import Data.List(intercalate)
f :: [String] -> IO String
f xs = intercalate "-" <$> mapM getEnv xs

I'll be honest, the idea behind your approach actually looks pretty sane to me. To start with, I'd probably use concat intsead of foldl1 (++), and drop some parens, getting us to:
f x y = concat <$> sequence [getEnv x, return "-", getEnv y]
This really doesn't seem that bad to me. But if I really wanted to push farther, here's some thoughts I would have. First, I'd recall the intercalate function.
f x y = intercalate "-" <$> sequence [getEnv x, getEnv y]
There's a handy shorthand for applying a function to each element of a list, too; mapM f = sequence . map f. So:
f x y = intercalate "-" <$> mapM getEnv [x,y]
I would stop there; it looks quite clean and maintainable to me.

One way of joining two IO Strings would be:
dash :: IO String -> IO String -> IO String
dash x y = do
s1 <- x
s2 <- y
return $ s1 <> "-" <> s2
We "unbox" each of x and y to get the contained Strings, then "rebox` them with a hyphen (using the analogy for Functors).
It can be shortened to:
dash = liftA2 (\s1 s2 -> s1 <> "-" <> s2)
Where liftA2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c takes a binary function and "lifts" it into a binary function on Applicatives, which are a superset of Monads.
Your f can then be implemented as f x y = dash (getEnv x) (getEnv y).

Related

haskell parser combinator infinite loop

I'm trying to write a simple parser via Haskell, but stuck at an infinite loop.
the code is:
import Control.Applicative (Alternative, empty, many, (<|>))
data Parser a = Parser {runParser :: String -> [(a, String)]}
instance Functor Parser where
fmap f (Parser p) = Parser $ \s -> [(f x', s') | (x', s') <- p s]
instance Applicative Parser where
pure x = Parser $ \s -> [(x, s)]
(Parser pf) <*> (Parser p) = Parser $ \s -> [(f' x, ss') | (f', ss) <- pf s, (x, ss') <- p ss]
instance Alternative Parser where
empty = Parser $ \s -> []
(Parser p1) <|> (Parser p2) = Parser $ \s ->
case p1 s of
[] -> p2 s
xs -> xs
singleSpaceParser :: Parser Char
singleSpaceParser = Parser $ \s ->
( case s of
x : xs -> if x == ' ' then [(' ', xs)] else []
[] -> []
)
multiSpaceParser :: Parser [Char]
multiSpaceParser = many singleSpaceParser
I just load this file in ghci, and run:
runParser multiSpaceParser " 123"
I expect it to get [(" ", "123")], but actually it got an infinite loop
I used trace to debug, and it seems that many is wrong
How can I fix this bug?
Let's assume
many p = (:) <$> p <*> many p <|> pure []
and consider the call
many singleSpaceParser " 123"
(The string does not actually matter here, the many singleSpaceParser call will always loop.)
One reduction step yields
((:) <$> singleSpaceParser <*> many singleSpaceParser <|> pure []) " 123"
Now observe that, in order to reduce the call to (<|>), we have to evaluate both arguments of (<|>) to be of the shape Parser ....
Let's consider doing that for (:) <$> singleSpaceParser <*> many singleSpaceParser. As both (<$>) and (<*>) are infixl 4, this is an application of <*> at the outermost level.
But now observe that in order to reduce (<*>), we again have to evaluate both arguments of (<*>) to be of the shape Parser ..., so in particular the recursive call many singleSpaceParser.
This is where we get the infinite loop.
By switching data to newtype (or alternatively, at least avoiding aggressively pattern-matching on the Parser constructor in all the second arguments), these problems can be avoided.

haskell, the same program using monads

As you can see, I wrote program, e.g:
test "12 124 212" = Right [12, 124, 212]
test "43 243 fs3d 2" = Left "fs3d is not a number"
test :: String -> Either String [Int]
test w = iter [] $ words w
where
iter acc [] = Right (reverse acc)
iter acc (x:xs) = if (all isDigit x) then
iter ((read x):acc) xs
else
Left (x++ "is not a number")
A am starting learning monads. Could you show me how to implement it using monads ?
I think you are looking for traverse/mapM (they're the same for lists). Also you can use readEither for simplification:
import Data.Traversable (traverse)
import Data.Bifunctor (first)
import Text.Read (readEither)
test :: String -> Either String [Int]
test = traverse parseItem . words
parseItem :: String -> Either String Int
parseItem x = first (const $ x++" is not a number") $ readEither x
So what does mapM do? It basically implements the recursion over the list that you did manually. However, unlike the standard map function it takes a monadic function (parseItem in our case, where Either String is a monad) and applies one step on the list after the other:
iter [] = Right []
iter (x:xs) = do
r <- parseItem x
rs <- iter xs
return (r:rs)
Bergi's answer is just right, but maybe you'll find it easy to understand presented this way:
test :: String -> Either String [Int]
test str = traverse parseNumber (words str)
parseNumber :: String -> Either String Int
parseNumber str
| all isDigit str = Right (read str)
| otherwise = Left (str ++ " is not a number")
The other thing I'd recommend is don't write tail-recursive accumulator loops like iter in your example. Instead, look at library documentation and try to find list functions that do what you want. In this case, as Bergi correctly pointed out, traverse is exactly what you want. It will take some study to get fully comfortable with this function, though. But given how the Monad instance of Either and the Traversable instance of lists work, the traverse in this example works like this:
-- This is the same as `traverse` for lists and `Either`
traverseListWithEither :: (a -> Either err b) -> [a] -> Either err [b]
traverseListWithEither f [] = Right []
traverseListWithEither f (a:as) =
case f a of
Left err -> Left err
Right b -> mapEither (b:) (traverseListWithEither f as)
-- This is the same as the `fmap` function for `Either`
mapEither :: (a -> b) -> Either e a -> Either e b
mapEither f (Left e) = Left e
mapEither f (Right a) = Right (f a)

Is there a point-free way to convert a conditional check into a Maybe type of the input?

I am just working through some simple exercises in haskell and was wondering if there was a point-free way of converting an if-then-else statement into a Maybe type: Nothing being returned if the condition is false, and Just the input if the condition is true.
In short, given some:
maybeIf :: (a -> Bool) -> a -> Maybe a
maybeIf cond a = if cond a then Just a else Nothing
Is there an implementation that is point-free with respect to a? I've also been looking at a more concrete version, a -> Maybe a, and feel like there may be an answer somewhere in Control.Arrow. However, since Maybe is a data type and if-else statements control data flow, I'm unsure if there is a clean way of doing it.
The main thing getting in the way of making that pointfree is the if/then/else. You can define an if' combinator, or you can use this generalized version that I define and use often:
ensure p x = x <$ guard (p x)
Standard tools give successive point-free versions as
ensure p = ap (<$) (guard . p)
ensure = ap (<$) . (guard .)
though I really don't think either are better than the pointful version.
You can import find from Data.Foldable and then it's quite simply:
import Data.Foldable(find)
maybeIf cond = find cond . Just
The function find is not complicated so you could quite easily define it yourself less generically, in terms of Maybe, but it isn't actually so different from your own implementation of maybeIf so you might not gain much, depending on why you wanted to do it.
If we choose a Church-encoding for Booleans…
truth :: Bool -> a -> a -> a
truth True t f = t
truth False t f = f
Then we can write a point-free maybeIf in Applicative-style.
maybeIf :: (a -> Bool) -> a -> Maybe a
maybeIf = liftA3 truth <*> pure Just <*> pure (pure Nothing)
Some intuitions…
f <$> m₁ <*> … <*> mₙ = \x -> f (m₁ x) … (mₙ x)
liftAₙ f <$> m₁ <*> … <*> mₙ = \x -> f <$> m₁ x <*> … <*> mₙ x
Here is a rendering in PNG format of the above "intuitions", in case your installed fonts do not support the needed unicode characters.
So therefore:
liftA3 truth <*> pure Just <*> pure (pure Nothing)
= liftA3 truth <$> id <*> pure Just <*> pure (pure Nothing)
= \p -> truth <$> id p <*> (pure Just) p <*> (pure (pure Nothing)) p
= \p -> truth <$> p <*> Just <*> pure Nothing
= \p -> \a -> truth (p a) (Just a) ((pure Nothing) a)
= \p -> \a -> truth (p a) (Just a) Nothing
Following dfeuer's lead (and using Daniel Wagner's new name for this function),
import Data.Bool (bool)
-- F T
-- bool :: a -> a -> Bool -> a
ensure :: (a -> Bool) -> a -> Maybe a
ensure p x = bool (const Nothing) Just (p x) x
ensure p = join (bool (const Nothing) Just . p)
= bool (const Nothing) Just =<< p
ensure = (bool (const Nothing) Just =<<)
join is a monadic function, join :: Monad m => m (m a) -> m a, but for functions it is simply
join k x = k x x
(k =<< f) x = k (f x) x
join is accepted as a replacement for W combinator in point-free code.
You only wanted it point-free with respect to the value argument, but it's easy to transform the equation with join further (readability of the result is another issue altogether), as
= join ((bool (const Nothing) Just .) p)
= (join . (bool (const Nothing) Just .)) p
Indeed,
#> (join . (bool (const Nothing) Just .)) even 3
Nothing
#> (bool (const Nothing) Just =<<) even 4
Just 4
But I'd much rather see \p x -> listToMaybe [x | p x] in an actual code.
Or just \p x -> [x | p x], with Monad Comprehensions. Which is the same as Daniel Wagner's x <$ guard (p x), only with different syntax.
This function is defined in Control.Monad.Plus and is called partial

Haskell Parser fmap clarification

I have trouble in understanding the following fmap instance.Can someone explain me what fmap do(in this case) and how it can be used? Or write it less obfuscated?
Thanks!
newtype Parser a = P { getParser :: String -> Maybe (a, String) }
instance Functor Parser where
fmap f (P p) = P $ \s -> fmap (applyToFirst f) $ p s
{-|
Applies a function to the first component of a pair.
-}
applyToFirst :: (a -> b) -> (a, c) -> (b, c)
applyToFirst f (x, y) = (f x, y)
What does it do?
It transforms a parser X into parser Y, where Y does the following: runs parser X and applies function f to first element of parsing result pair.
How to use it?
p1 :: Parser String
p1 = P (\s -> Just ("foo", "bar"))
p2 :: Parser String
p2 = fmap (\s -> s ++ s) p1
Now (getParser p2) "whatever" equals Just ("foofoo", "bar").
Could it be less obfuscated?
It is not obfuscated actually. Haskell takes time to get used to.

Trick for "reusing" arguments in Haskell?

From time to time I stumble over the problem that I want to express "please use the last argument twice", e.g. in order to write pointfree style or to avoid a lambda. E.g.
sqr x = x * x
could be written as
sqr = doubleArgs (*) where
doubleArgs f x = f x x
Or consider this slightly more complicated function (taken from this question):
ins x xs = zipWith (\ a b -> a ++ (x:b)) (inits xs) (tails xs)
I could write this code pointfree if there were a function like this:
ins x = dup (zipWith (\ a b -> a ++ (x:b))) inits tails where
dup f f1 f2 x = f (f1 x) (f2 x)
But as I can't find something like doubleArgs or dup in Hoogle, so I guess that I might miss a trick or idiom here.
From Control.Monad:
join :: (Monad m) -> m (m a) -> m a
join m = m >>= id
instance Monad ((->) r) where
return = const
m >>= f = \x -> f (m x) x
Expanding:
join :: (a -> a -> b) -> (a -> b)
join f = f >>= id
= \x -> id (f x) x
= \x -> f x x
So, yeah, Control.Monad.join.
Oh, and for your pointfree example, have you tried using applicative notation (from Control.Applicative):
ins x = zipWith (\a b -> a ++ (x:b)) <$> inits <*> tails
(I also don't know why people are so fond of a ++ (x:b) instead of a ++ [x] ++ b... it's not faster -- the inliner will take care of it -- and the latter is so much more symmetrical! Oh well)
What you call 'doubleArgs' is more often called dup - it is the W combinator (called warbler in To Mock a Mockingbird) - "the elementary duplicator".
What you call 'dup' is actually the 'starling-prime' combinator.
Haskell has a fairly small "combinator basis" see Data.Function, plus some Applicative and Monadic operations add more "standard" combinators by virtue of the function instances for Applicative and Monad (<*> from Applicative is the S - starling combinator for the functional instance, liftA2 & liftM2 are starling-prime). There doesn't seem to be much enthusiasm in the community for expanding Data.Function, so whilst combinators are good fun, pragmatically I've come to prefer long-hand in situations where a combinator is not directly available.
Here is another solution for the second part of my question: Arrows!
import Control.Arrow
ins x = inits &&& tails >>> second (map (x:)) >>> uncurry (zipWith (++))
The &&& ("fanout") distributes an argument to two functions and returns the pair of the results. >>> ("and then") reverses the function application order, which allows to have a chain of operations from left to right. second works only on the second part of a pair. Of course you need an uncurry at the end to feed the pair in a function expecting two arguments.

Resources