I'm new to Haskell and i'm now watching the "Haskell Rank" series on youtube and i feel i need a better understanding of what's going on in the first video so i can move on.
He starts with the basic "solve me first" exercise on hackerrank, which already comes with the solution:
solveMeFirst a b = a + b
main = do
val1 <- readLn
val2 <- readLn
let sum = solveMeFirst val1 val2
print sum
this is clear, if i put it in a file, compile it and run it, it behaves as expected:
takes two lines of input
prints the sum of the numbers from the user input
through several steps of explaining the roles of each function, he reaches a more functional one-line solution;
he gets there by first working up to the following:
> show $ sum $ map read $ words "1 2"
3
Up until here, i understand everything, including the use of the ($) operator.
To finish, he then defines the main function, using interact to handle the input from stdinand there are two things i really don't understand:
1 - the function composition: he then reaches the solution of:
main = interact $ show . sum . map read . words
where he grabs the previous build up, removes the input "1 2" to compose the function that will be the argument for interact. And, what he doesn't explain thoroughly is "and replace all of its dollar signs with functional composition."
Would love a detailed explanation of step-by-stepping this "inversion" process.
2 - using this one-line solution, and compiling it from a file,
how can i run the file, sending the input as args?
The conversion to composition is based on the simple definition of the . operator (shown here using $ to make the link clear).
(.) f g = \x -> f $ g x
show . sum . map read . words is the same as \x -> show $ sum $ map read $ words x.
The composed function is never explicitly applied to an argument because interact takes the function and produces an IO () value which, when executed by the runtime, will apply the function to an argument also supplied by the runtime.
The runtime supplies the input by reading from standard input.
Related
I want to do some infinite sequence of IO actions processing with filtration their results in realtime+perfoming some IO actions in certain moments:
We have some function for reducing sequences (see my question haskell elegant way to filter (reduce) sequences of duplicates from infinte list of numbers):
f :: Eq a => [a] -> [a]
f = map head . group
and expression
join $ sequence <$> ((\l -> (print <$> l)) <$> (f <$> (sequence $ replicate 6 getLine)))
if we run this, user can generate any seq of numbers, for ex:
1
2
2
3
3
"1"
"2"
"3"
[(),(),()]
This means that at first all getLine actions performed (6 times in the example and at the end of this all IO actions for filtered list performed, but I want to do IO actions exactly in the moments then sequencing reduces done for some subsequences of same numbers.
How can I archive this output:
1
2
"1"
2
3
"2"
3
3
"3"
[(),(),()]
So I Want this expression not hangs:
join $ sequence <$> ((\l -> (print <$> l)) <$> (f <$> (sequence $ repeat getLine)))
How can I archive real-time output as described above without not blocking it on infinite lists?
Without a 3rd-party library, you can lazily read the contents of standard input, appending a dummy string to the end of the expected input to force output. (There's probably a better solution that I'm stupidly overlooking.)
import System.IO
print_unique :: (String, String) -> IO ()
print_unique (last, current) | last == current = return ()
| otherwise = print last
main = do
contents <- take 6 <$> lines <$> hGetContents stdin
traverse print_unique (zip <*> tail $ (contents ++ [""]))
zip <*> tail produces tuples consisting of the ith and i+1st lines without blocking. print_unique then immediately outputs a line if the following line is different.
Essentially, you are sequencing the output actions as the input is executed, rather than sequencing the input actions.
This seems like a job for a streaming library, like streaming.
{-# LANGUAGE ImportQualifiedPost #-}
module Main where
import Streaming
import Streaming.Prelude qualified as S
main :: IO ()
main =
S.mapM_ print
. S.catMaybes
. S.mapped S.head
. S.group
$ S.replicateM 6 getLine
"streaming" has an API reminiscent to that of lists, but works with effectful sequences.
The nice thing about streaming's version of group is that it doesn't force you to keep the whole group in memory if it isn't needed.
The least intuitive function in this answer is mapped, because it's very general. It's not obvious that streaming's version of head fits as its parameter. The key idea is that the Stream type can represent both normal effectful sequences, and sequences of elements on which groups have been demarcated. This is controlled by changing a functor type parameter (Of in the first case, a nested Stream (Of a) m in the case of grouped Streams).
mapped let's you transform that functor parameter while having some effect in the underlying monad (here IO). head processes the inner Stream (Of a) m groups, getting us back to an Of (Maybe a) functor parameter.
I found a nice solution with iterateUntilM
iterateUntilM (\_->False) (\pn -> getLine >>= (\n -> if n==pn then return n else (if pn/="" then print pn else return ()) >> return n) ) ""
I don't like some verbose with
(if pn/="" then print pn else return ())
if you know how to reduce this please comment)
ps.
It is noteworthy that I made a video about this function :)
And could not immediately apply it :(
I'm playing with the interact function from Prelude, wanting to do a simple REPL evaluating my inputs line by line, and I cannot understand what's going on.
If I make it simple like this:
main :: IO ()
main = interact interaction
interaction :: String -> String
interaction (x:xs) = xs
interaction x = x
Then it behaves ok, and removes the first character from my input, or returns the input if it is only one character long.
What puzzles me is if add this line:
interaction :: String -> String
interaction x | length x > 10 = "long word" -- this line causes problem
interaction (x:xs) = xs
interaction x = x
Then, interact seems not to work correctly any longer.
It just awaits for my input, swallows it awaiting another input and so on, but never outputs anything.
It seems so simple however, but I cannot see what is going wrong.
Any idea ?
(On my path I have GHC 7.6.3, I don't know if it has some importance.)
With what you've written, you're trying to calculate the length of the whole input sequence, so your program has to wait for the entire sequence to be available.
You could try a lazy pattern-match like this:
interaction (x1:x2:x3:x4:x5:x6:x7:x8:x9:x10:x11:_) = "long word"
This allows you to ignore the rest of the input once you know you've reached 10 characters.
A cleaner/more general alternative (suggested by #amalloy) that scales for bigger lengths and allows a variable length guard would be something like:
interaction xs | not . null . drop 10 $ xs = "long word"
If what you really want to do is process your input a line at a time, and produce this message for an individual line longer than 10 characters, you can use lines and unlines to make your interaction function line-oriented rather than character-oriented, e.g.:
main :: IO ()
main = interact (unlines . interaction . lines)
interaction :: [String] -> [String]
interaction (x:_) | length x > 10 = "long word" -- this is just looking at the first line
...
or maybe if you want to do that for every line, not just the first:
main :: IO ()
main = interact (unlines . map interaction . lines)
interaction :: String -> String
interaction x | length x > 10 = "long word"
...
interact takes the entirety of standard input at once, as one big string. You call length on all of stdin, and so your function cannot return until stdin is exhausted entirely. You could, for example, hit ctrl-D (assuming Unix) to send EOF, and then your function will finally find out what stdin's length is.
I would like to allow a user to build a list from a series of inputs in Haskell.
The getLine function would be called recursively until the stopping case ("Y") is input, at which point the list is returned.
I know the function needs to be in a similar format to below. I am having trouble assigning the correct type signatures - I think I need to include the IO type somewhere.
getList :: [String] -> [String]
getList list = do line <- getLine
if line == "Y"
then return list
else getList (line : list)
So there's a bunch of things that you need to understand. One of them is the IO x type. A value of this type is a computer program that, when later run, will do something and produce a value of type x. So getLine doesn't do anything by itself; it just is a certain sort of program. Same with let p = putStrLn "hello!". I can sequence p into my program multiple times and it will print hello! multiple times, because the IO () is a program, as a value which Haskell happens to be able to talk about and manipulate. If this were TypeScript I would say type IO<x> = { run: () => Promise<x> } and emphatically that type says that the side-effecting action has not been run yet.
So how do we manipulate these values when the value is a program, for example one that fetches the current system time?
The most fundamental way to chain such programs together is to take a program that produces an x (an IO x) and then a Haskell function which takes an x and constructs a program which produces a y (an x -> IO y and combines them together into a resulting program producing a y (an IO y.) This function is called >>= and pronounced "bind". In fact this way is universal, if we add a program which takes any Haskell value of type x and produces a program which does nothing and produces that value (return :: x -> IO x). This allows you to use, for example, the Prelude function fmap f = (>>= return . f) which takes an a -> b and applies it to an IO a to produce an IO b.
So It is so common to say things like getLine >>= \line -> putStrLn (upcase line ++ "!") that we invented do-notation, writing this as
do
line <- getLine
putStrLn (upcase line ++ "!")
Notice that it's the same basic deal; the last line needs to be an IO y for some y.
The last thing you need to know in Haskell is the convention which actually gets these things run. That is that, in your Haskell source code, you are supposed to create an IO () (a program whose value doesn't matter) called Main.main, and the Haskell compiler is supposed to take this program which you described, and give it to you as an executable which you can run whenever you want. As a very special case, the GHCi interpreter will notice if you produce an IO x expression at the top level and will immediately run it for you, but that is very different from how the rest of the language works. For the most part, Haskell says, describe the program and I will give it to you.
Now that you know that Haskell has no magic and the Haskell IO x type just is a static representation of a computer program as a value, rather than something which does side-effecting stuff when you "reduce" it (like it is in other languages), we can turn to your getList. Clearly getList :: IO [String] makes the most sense based on what you said: a program which allows a user to build a list from a series of inputs.
Now to build the internals, you've got the right guess: we've got to start with a getLine and either finish off the list or continue accepting inputs, prepending the line to the list:
getList = do
line <- getLine
if line == 'exit' then return []
else fmap (line:) getList
You've also identified another way to do it, which depends on taking a list of strings and producing a new list:
getList :: IO [String]
getList = fmap reverse (go []) where
go xs = do
x <- getLine
if x == "exit" then return xs
else go (x : xs)
There are probably several other ways to do it.
I'm very new to Haskell and I'm trying to understand these basic lines of code. I have a main module that's very simple:
main = do
words <- readFile "test.txt"
putStrLn $ reverseCharacters words
where reverseCharacters is defined in another module that I have:
reverseCharacters :: String -> String
reverseCharacters x = reverse x
What I am having trouble understanding is why the $ needs to be there. I've read previous posts and looked it up and I'm still having difficulty understanding this. Any help would be greatly appreciated.
$ is an operator, just like +. What it does is treat its first argument (the expression on the left) as a function, and apply it to its second argument (the expression on the right).
So in this case putStrLn $ reverseCharacters words is equivalent to putStrLn (reverseCharacters words). It needs to be there because function application is left associative, so using no $ or parentheses like putStrLn reverseCharacters words would be equivalent to parenthesising this way (putStrLn reverseCharacters) words, which doesn't work (we can't apply putStrLn to reverseCharacters [something of type String -> String], and even if we could we can't apply the result of putStrLn to words [something of type String]).
The $ operator is just another way of explicitly "grouping" the words than using parentheses; because it's an infix operator it forces a "split" in the expression (and because it's a very low precedence infix operator, it works even if the things on the left or right are using other infix operators).
I am currently learning Haskell and I have a hard time to see What are the common ways to save intermediaries result in Haskell.
For example, let's say that I have a program that take a file, produce some intermediary results and then take some parameters and use the result of the first step to produce something else. Plus, let's say that at the end the user could change the parameters to produce new output but the processing of the first step should not be redone in order to reduce the computation time.
Basically, I just need to temporally save the result of the first step. This would be fairly simple for me in a OO way but because of Haskell purity I don't see a convenient way to solve this.
There are many ways to deal with intermediate results in Haskell. It sounds to me like you would like your main function to look something like this. I will assume you have some function that produces an intermediate result (runFirstStep), a function that prompts for settings (promptForSettings), and a function that uses the intermediate result and the settings to produce a final value (runSecondStep)
main :: IO ()
main = do
-- setup, compute shared value
intermediate <- runFirstStep
-- processing
-- prompt for settings here
settings <- promptForSettings
final <- runSecondStep intermediate settings
-- and done
print final
If you want a more complex control-flow, you could define a separate function, like so:
main :: IO ()
main = do
-- setup, compute shared value
intermediate <- runFirstStep
-- run the second step computation
processLoop intermediate
print final
processLoop :: intermediate -> IO final
processLoop intermediate = do
settings <- promptForSettings
final <- runSecondStep intermediate settings
-- check if user wants to run with different settings
rerun <- do
putStrLn "Run again? [Y/n]"
result <- getStrLn
return (result != "n")
if rerun
then process
else return final
If you are interested in more complex control flows that are impure, there are many ways to store intermediate computations in memory using a variety of techniques. The lowest level and most difficult to get right is to use IORef. Above that, you can use MVar as a way of signalling and locking sections of code based on some shared state, but even that can be tricky to get right. At the highest level, ST and STM let you handle shared state in much more complex ways and are easier to reason about.
An example: You want to read in a bunch of numbers and then compute different sums of powers of those numbers (sums of squares, sums of cubes, etc.)
The first step is to "ignore the IO" - forget for the moment how you are going to get the numbers and the power parameter - and concentrate on the function that does meat of the work - computes the sums of n-th powers of a list of numbers.
powersum :: [Double] -> Int -> Double
powersum xs n = sum $ map (^n) xs
We'll want to compute power sums for various exponents. Again, I would forget about what you are going to do with them later, whether it be print them out, sort them, etc. and write a function which does the computation:
powersums :: [Double] -> [Int] -> [Double]
powersums xs ns = map (powersum xs) ns
Now let's hook it up to the real world. Let's first consider the case when we know the exponents in advance but read the numbers from standard input (all on a single line.)
main = do line <- getLine -- IO
let nums = map read (words line) \
let exponents = [1..10] | - pure code
let sums = powersums nums exponents /
print sums -- IO
Note how our IO sandwiches our pure code - this is very typical of functional programs.
Now suppose you want to also read in the exponents from stdin, and print out the power sums of each read exponent. You could write an imperative-style program like this:
main = do line <- getLine
let nums = map read (words line)
forever $ do exp <- read `fmap` getLine
putStrLn $ show $ powersum nums exp
This illustrates how data (nums in this case) is being stored for use by other parts of the program.