Avoiding mutable state to update String - haskell

I'm attempting to write a function that will continually loop checking if a randomly generated int is less than 5, if it is less than 5 then "e" is appended to a string, once "eee" is generated then exit out of the loop.
This Haskell code prints if a random value between 1 - 10 is less than 5 :
useInt :: Int -> Int
useInt x = x
test :: IO ()
test = do
let l = "eee";
int <- randomRIO (1, 10) :: IO Int
if(int < 5) then
putStrLn "less"
else
putStrLn "greater"
test
But I'm unsure how to modify a string without introducing mutable state.
To achieve this using pseudo haskell code can use :
var mutableString = "" :
useInt :: Int -> Int
useInt x = x
test :: IO ()
test = do
let l = "eee";
int <- randomRIO (1, 10) :: IO Int
while(mutableString != "eee"){
if(mutableString == "eee")
break out of loop
else
if(int < 5) then
mutableString = mutableString + "e"
putStrLn "less"
else
putStrLn "greater"
}
test
Any pointers to translate above pseudo code to valid Haskell ?

Use recursion:
test :: IO ()
test = let
loop "eee" = putStrLn "ending" -- end of the "loop"
loop l = do -- "loop" iteration
int <- randomRIO (1, 10) :: IO Int
if int < 5
then do
putStrLn "less"
loop l -- same value for l
else do
putStrLn "greater"
loop ('e':l) -- updated value for l
in loop "" -- "loop" start with initial value for l
The idea is that loop l takes as a parameter the current value of the "mutable" l. When we recurse, we pass the new value of l. In the then branch above we pass the same value since we don't want to modify it. In the else branch we prepend an 'e' character.

Related

How to do multiple things in a Haskell function?

I was wondering, how can we do multiple things in a Haskell function?
For example, I have this code:
number = 0
increment :: Int -> Int
increment i = i + 1
function :: String -> String
function s = s ++ " world" AND increment number
I was wondering, how can we do something like this? I'm searching everywhere but I don't find a solution for this simple example :O
number
0
:function "hello"
"hello world" (AND the number = 1 now)
number
1
note: I know that AND is not a syntax in Haskell but I wanted to make you understand what I wanted to say :)
You can't modify variables in Haskell (they are not, in fact, variable). What you can do is return new values:
f (string, number) = (string ++ " world", number + 1)
which would be used like this:
Prelude> f ("hello", 0)
("hello world",1)
If you called this function with a variable instead of a literal, it would not change the value of that variable, because Haskell is designed to prevent that from happening:
Prelude> let n = 0
Prelude> f ("hello", n)
("hello world",1)
Prelude> print n
0
the problem is: in haskell you don't have "mutable states" like in other programming languages: so "number = 1" wouldn't work in terms of "setting a State"
you could combine them as a result:
increment :: Int -> Int
increment i = i + 1
stringCombine :: String -> String
stringcombine str = str ++ "world"
combine i str = (increment i, stringCombine str)
or if you have a function with a side effect (like print, putStrLn) you have to use the IO Monad:
doSideEffects :: Int -> String -> IO Int
doSideEffects i str = do
putStrLn $ str ++ "world"
return $ increment i

Executing a function randomly of a list of functions

=== Evaluation of HStatement (bar if and selection) ===
evalStatement_ :: Env -> HStatement -> IOThrowsError ()
evalStatement_ env (Do cond expr) = evalVal env cond >>= \x -> case x of
HBool False -> return ()
HBool True -> do
traverse_ (evalStatement_ env) expr
evalStatement_ env (Do cond expr)
evalStatement_ env (Skip skip) = return ()
evalStatement_ env (Print (HString val)) = getVar env val >>= \x -> liftIO $ putStrLn $ show x
evalStatement_ env (Print val) = evalVal env val >>= \x -> liftIO $ putStrLn $ show x
evalStatement_ env (Eval val) = do
result <- evalVal env val
return ()
=== Representation of Selection & If ===
parseIf :: Parser HStatement
parseIf = do
string "("
cond <- parseArith
string ")->"
spaces
expr <- many1 $ parseStatements
spaces
return $ If (cond, expr)
parseSelection :: Parser HStatement
parseSelection = do
_ <- string "if"
spaces
selection <- many1 $ parseIf
spaces
_ <- string "fi"
spaces
return $ Selection selection
N.B : If evaluation of selection is changed to the below, then the program runs and terminates and does give output:
evalStatement_ env (Selection if_ selection fi_ n) = evalStatement_ env (selection !! randIdx n) >>= \res -> if res == ()
then return ()
else return ()
The output however gives varying amounts of the even integers between 1 and 10. For example one output would print all even integers and another prints on the number 6.
tldr; is there a way to execute a random function from a list of functions randomly and if the result is not ideal, reexecute the function to execute a random function until the result is idea?
I'm trying to write a function which executes a random entry in a list of functions. Each entry in the list is constructed in the following way: If (HVal, HStatement) -- If (Guard,Statement) where
HVal:
data HVal
= HInteger Integer
HBool Bool
HString String
HList [HVal]
Length HVal
Arith HVal Op HVal
Assign String HVal
deriving (Eq, Read)
HStatement:
data HStatement
= Eval HVal
| Print HVal
| Do HVal [HStatement]
| If (HVal, [HStatement])
| Selection [HStatement]
deriving (Eq, Read)
What I tried so far was using Asyncs race function as per my question yesterday. My thinking behind this was if there exists a list of n entries in a list that are constructed as If (HVal, HStatement), then running a race function over a list that only contain a list of HStatements whose guards were evaluated to true would return the function that executes the fastest of the true guards.
Trying to incorporate this raceAll behaviour into my code base proved to be too difficult to me due to the constraint of IO. I redid the approach by considering using a random number generator.
So now I'm generating a random index of the list of guard statements pairs. I execute the entry in this list and perform a case analysis. If the output is () then I call the function again otherwise I return the output. To do this I'm using two functions wherein selection represents a list of if's:
evalStatement_ env (If (cond, expr)) = evalVal env cond >>= \x -> case x of
HBool False -> return ()
HBool True -> traverse_ (evalStatement_ env) expr
evalStatement_ env (Selection selection) = evalStatement_ env (selection !! randIdx 1) >>= \res -> case res of -- randIdx produces an index between 0 and 1 representing the two branches in the selection block that could be taken
() -> evalStatement_ env (Selection selection)
_ -> return $ res
randIdx n = unsafePerformIO (getStdRandom (randomR (0, n - 1)))
Take the following program as example:
f := [1 2 3 4 5 6 7 8 9 10]
n := 0
N := len(f)
Do (n < N)->
a := f.n
if ((a % 2) = 0)-> print(a)
((a % 1) = 1)-> print(a)
fi
n := n + 1
Od
What occurs here is that the program gives no output at all and doesn't terminate. What I would have expected to happen was that a random index is generated between 0 and the number of possible branches minus one. Then this would have been evaluated and if it returned a value, this would have been taken otherwise if it was the unit type, a new random index would have been generated and that would have been used.
I can execute the program however if the function definition for selection is traverse_ (evalStatement_ env) selection but I'm just unsure on how to achieve this pseudo randomness. Any help would be appreciated!
You say,
If the output is () then I call the function again otherwise I return the output.
This is a strange thing to say, because there is no "otherwise" -- if your thing returns () sometimes, it can never return anything but (), because there is no other value with the same type! In particular, this means it is impossible to reach the _ branch of your case.
In your language as shown here, statements fundamentally do not compute data. Perhaps you should change your Selection constructor to take an [(HVal, HStatement)] instead of an [HStatement] (representing pairs of the computation that returns something interesting that you can case on together with the statement to execute in some appropriate branch of that case), or modify the type that statements compute to something richer than ().

Simple Haskell program not behaving correct

I'm new to Haskell and trying to write simple program to find maximal element and it's index from intput. I receive values to compare one by one. Maximal element I'm holding in maxi variable, it's index - in maxIdx. Here's my program:
loop = do
let maxi = 0
let maxIdx = 0
let idx = 0
let idxN = 0
replicateM 5 $ do
input_line <- getLine
let element = read input_line :: Int
if maxi < element
then do
let maxi = element
let maxIdx = idx
hPutStrLn stderr "INNER CHECK"
else
hPutStrLn stderr "OUTER CHECK"
let idx = idxN + 1
let idxN = idx
print maxIdx
loop
Even though I know elements coming are starting from bigger to smaller (5, 4, 3, 2, 1) program enters INNER CHECK all the time (it should happen only for the first element!) and maxIdx is always 0.
What am I doing wrong?
Thanks in advance.
Anyway, let's have fun.
loop = do
let maxi = 0
let maxIdx = 0
let idx = 0
let idxN = 0
replicateM 5 $ do
input_line <- getLine
let element = read input_line :: Int
if maxi < element
then do
let maxi = element
let maxIdx = idx
hPutStrLn stderr "INNER CHECK"
else
hPutStrLn stderr "OUTER CHECK"
let idx = idxN + 1
let idxN = idx
print maxIdx
loop
is not a particularly Haskelly code (and as you know is not particularly correct).
Let's make if Haskellier.
What do we do here? We've an infinite loop, which is reading a line 5 times, does something to it, and then calls itself again for no particular reason.
Let's split it:
import Control.Monad
readFiveLines :: IO [Int]
readFiveLines = replicateM 5 readLn
addIndex :: [Int] -> [(Int, Int)]
addIndex xs = zip xs [0..]
findMaxIndex :: [Int] -> Int
findMaxIndex xs = snd (maximum (addIndex xs))
loop :: ()
loop = loop
main :: IO ()
main = do xs <- readFiveLines
putStrLn (show (findMaxIndex xs))
snd returns the second element from a tuple; readLn is essentially read . getLine; zip takes two lists and returns a list of pairs; maximum finds a maximum value.
I left loop intact in its original beauty.
You can be even Haskellier if you remember that something (huge expression) can be replaced with something $ huge expression ($ simply applies its left operand to its right operand), and the functions can be combined with .: f (g x) is the same as (f . g) x, or f . g $ x (see? it's working for the left side as well!). Additionally, zip x y can be rewritten as x `zip` y
import Control.Monad
readFiveLines :: IO [Int]
readFiveLines = replicateM 5 readLn
addIndex :: [Int] -> [(Int, Int)]
addIndex = (`zip` [0..])
findMaxIndex :: [Int] -> Int
findMaxIndex = snd . maximum . addIndex
main :: IO ()
main = do xs <- readFiveLines
putStrLn . show . findMaxIndex $ xs
As for debug print, there's a package called Debug.Trace and a function traceShow which prints its first argument (formatted with show, hence the name) to stderr, and returns its second argument:
findMaxIndex :: [Int] -> Int
findMaxIndex = snd . (\xs -> traceShow xs (maximum xs)) . addIndex
That allows you to tap onto any expression and see what's coming in (and what are the values around — you can show tuples, lists, etc.)
I think alf's answer is very good, but for what it's worth, here's how I would interpret your intention.
{-# LANGUAGE FlexibleContexts #-}
module Main where
import System.IO
import Control.Monad.State
data S = S { maximum :: Int
, maximumIndex :: Int
, currentIndex :: Int }
update :: Int -> Int -> S -> S
update m mi (S _ _ ci) = S m mi ci
increment :: S -> S
increment (S m mi ci) = S m mi (ci+1)
next :: (MonadIO m, MonadState S m) => m ()
next = do
S maxi maxIdx currIdx <- get
input <- liftIO $ getLine
let element = read input :: Int
if maxi < element
then do
modify (update element currIdx)
liftIO $ hPutStrLn stderr "INNER CHECK"
else
liftIO $ hPutStrLn stderr "OUTER CHECK"
modify increment
run :: Int -> IO S
run n = execStateT (replicateM_ n next) (S 0 0 0)
main :: IO ()
main = do
S maxi maxIdx _ <- run 5
putStrLn $ "maxi: " ++ (show maxi) ++ " | maxIdx: " ++ (show maxIdx)
This uses a monad transformer to combine a stateful computation with IO. The get function retrieves the current state, and the modify function lets you change the state.

How could this code enter an infinite loop? aka how to implement a counter in Haskell?

I have this code inside a function with side effects ... -> IO()
let index_player = (-1)
dronePositionByPlayer <- replicateM nb_players $ do
let index_player = index_player + 1
dronePositions <- replicateM nb_drones $ do
input_line <- getLine
let input = words input_line
let dx = read (input!!0) :: Int
let dy = read (input!!1) :: Int
let dronePosition = DronePosition (Position dx dy) index_player
hPutStrLn stderr $ "position = " ++ show dronePosition
return (dronePosition)
return (dronePositions)
When I execute it, while parsing the input data (which is several lines containing each an x and y position) I have this trace on the stardard error output:
position = DronePosition (Position 703 892) Answer: <<loop>>
Obviously it can read the first position, but then it goes in infinite-loop, probably trying to display the field index_player.
DronePosition and Position are simple algebraic datatypes:
data Position = Position Int Int deriving Show
data DronePosition = DronePosition Position Drone deriving Show
What is ill-formed in my code ?
let index_player = index_player + 1
The above is a recursive definition, resulting in a index_player variable to be computed by adding one recursively -- forever. That does not terminate. It does not refer to the previous variable of the same name declared a few lines above.
If you want a loop, you can adapt e.g.
xs <- forM [0..100] $ \i -> do
print i
return (1000 + i)
The above prints all the numbers from 0 to 100, and defines xs to be the list of all the returned numbers, i.e. [1000..1100]. Remember to import Control.Monad to use forM.

Haskell: how to read values from stdin line-by-line and add them to a map?

I want to read strings from stdin and store them into a map, where key is the input string and value is the number of previous occurrences of this string. In Java I would have done something like this:
for (int i = 0; i < numberOfLines; i++) {
input = scanner.nextLine();
if (!map.containsKey(input)) {
map.put(input, 0);
System.out.println(input);
} else {
int num = map.get(input) + 1;
map.remove(input);
map.put(input, num);
System.out.println(input.concat(String.valueOf(num));
}
}
I've tried doing the same in Haskell by using forM_ but had no luck.
import Control.Monad
import qualified Data.Map as Map
import Data.Maybe
main = do
input <- getLine
let n = read input :: Int
let dataset = Map.empty
forM_ [1..n] (\i -> do
input <- getLine
let a = Map.lookup input dataset
let dataset' =
if isNothing a then
Map.insert input 0 dataset
else
Map.insert input num (Map.delete input dataset)
where num = ((read (fromJust a) :: Int) + 1)
let dataset = dataset'
let output = if isNothing a then
input
else
input ++ fromJust a
putStrLn output)
The contents of dataset in the above code does not change at all.
The Map defined in Data.Map is an immutable data type. Calling Map.insert returns a modified Map, it does not change the one you already have. What you want to do is iteratively apply updates in a loop. Something more like
import qualified Data.Map as M
import Data.Map (Map)
-- Adds one to an existing value, or sets it to 0 if it isn't present
updateMap :: Map String Int -> String -> Map String Int
updateMap dataset str = M.insertWith updater str 0 dataset
where
updater _ 0 = 1
updater _ old = old + 1
-- Loops n times, returning the final data set when n == 0
loop :: Int -> Map String Int -> IO (Map String Int)
loop 0 dataset = return dataset
loop n dataset = do
str <- getLine
let newSet = updateMap dataset str
loop (n - 1) newSet -- recursively pass in the new map
main :: IO ()
main = do
n <- fmap read getLine :: IO Int -- Combine operations into one
dataset <- loop n M.empty -- Start with an empty map
print dataset
Notice how this is actually less code (it's be even shorter if you just counted the number of occurrences, then updateMap dataset str = M.insertWith (+) str 1 dataset), and it separates the pure code from the impure.
In this case, you don't actually want to use forM_, because each step of the computation depends on the previous. It's preferred to write a recursive function that exits at a condition. If you so desired, you could also write loop as
loop :: Int -> IO (Map String Int)
loop n = go n M.empty
where
go 0 dataset = return dataset
go n dataset = getLine >>= go (n - 1) . updateMap dataset
Here I've compressed the body of the old loop into a single line and then put it inside go, this allows you to call it as
main :: IO ()
main = do
n <- fmap read getLine :: IO Int
dataset <- loop n
print dataset
This removes the need to know that you must pass in M.empty into loop for the first call, unless you have a use case to call loop multiple times on the same map.
Your problem is that Map.insert does not do what map.remove does in C++. Map.insert returns a new Map which has the element in it but you are simply throwing this new Map away. This is how nearly all Haskell data structures work, for instance the code:
main = do
let x = []
y = 5 : x
print x
prints the empty list []. The cons : operator does not destructively modify the empty list but returns a new list containing 5. Map.insert does the same but with Maps instead of lists.
First regarding your java code, you do not need to remove from the map before inserting a new value.
Regarding haskell, the language does not work the way you think it does : your let trick is not updating a value, everything is basically immutable in haskell.
Using only the basic getLine, one way to do it is to use recursion:
import qualified Data.Map as Map
type Dict = Map.Map String Int
makeDict ::Dict -> Int -> IO Dict
makeDict d remain = if remain == 0 then return d else do
l <- getLine
let newd = Map.insertWith (+) l 1 d
makeDict newd (remain - 1)
newDict count = makeDict Map.empty count

Resources