getLine x times haskell - haskell

Based on Hackerrank question
My problem is how can I do getLine t times on stdIn?
main = do
t <- getInt
let x = [divisorsInNumber unsafeGetInt | a <-[1..t] ]
print x
getInt :: IO Int
getInt = fmap read getLine
unsafeGetInt :: Int
unsafeGetInt = unsafePerformIO getInt
divisorsInNumber n = length $ filter (== True) $ map (isDivisor n) (integralToListOfInts n)

Just replicate t times the getLine operation with replicateM:
import Control.Monad (replicateM)
getLines :: Int -> IO [String]
getLines t = replicateM t getLine
Thus getInts, that is getInt t times, can be expressed with:
getInts :: Int -> IO [Int]
getInts = fmap read <$> getLines
The full code rewritten to use getInts could be:
import Control.Applicative ((<$>))
import Control.Monad (replicateM)
getLines :: Int -> IO [String]
getLines n = replicateM n getLine
getInts :: Int -> IO [Int]
getInts n = fmap read <$> getLines n
getInt :: IO Int
getInt = fmap read getLine
divisorsInNumber :: Int -> Int
divisorsInNumber n = length $ filter (isDivisor n) (integralToListOfInts n)
main :: IO ()
main = do
t <- getInt
nums <- getInts t
let x = [divisorsInNumber num | num <- nums]
print x

Related

Point free version for readMaybe

I want to write a function to read an Int without do notation. It works (see below), but I was wondering if it the bit around readMaybe can be written in point free form (or cleaned up a bit in some other way)?
main :: IO ()
main = getLine >>= (\x -> return $ (readMaybe x :: Maybe Int)) >>= print
Step 1: Replace the lambda with its pointfree equivalent:
main :: IO ()
main = getLine >>= return . (readMaybe :: String -> Maybe Int) >>= print
Step 2: Replace m >>= return . f with f <$> m:
main :: IO ()
main = (readMaybe :: String -> Maybe Int) <$> getLine >>= print
Step 3: Replace f <$> m >>= g with m >>= g . f:
main :: IO ()
main = getLine >>= print . (readMaybe :: String -> Maybe Int)
Step 4: Use a type application instead of writing out a long, awkward type:
{-# LANGUAGE TypeApplications #-}
main :: IO ()
main = getLine >>= print . readMaybe #Int
As an alternative to using <$> in steps 2 and 3, you can accomplish the same with just the monad laws, like this (picking up after step 1):
Replace m >>= f >>= g with m >>= \x -> f x >>= g (associativity):
main :: IO ()
main = getLine >>= \x -> (return . (readMaybe :: String -> Maybe Int)) x >>= print
Simplify the . away:
main :: IO ()
main = getLine >>= \x -> return ((readMaybe :: String -> Maybe Int) x) >>= print
Replace return x >>= f with f x (left identity):
main :: IO ()
main = getLine >>= \x -> print ((readMaybe :: String -> Maybe Int) x)
Now just replace that new lambda with its pointfree equivalent, and you end up in the exact same place as step 3.

Haskell get values from IO domain

After reading the Haskell books I am kind of confused (or I simply forgot) how to get a value from the IO domain, into the 'Haskell world' to parse it, like so:
fGetSeq = do
input <- sequence [getLine, getLine, getLine]
fTest input
mapM_ print input
fTest = map (read :: String -> Int)
Obviously compiler complains. Couldn't match [] with IO. Is there a simple rule of thumb for passing values between 'worlds' or is it just my bad by omitting typesigs?
The thing about do notation is, every monadic action value in it (those to the right of <-s, or on their own line) must belong to the same monad. It's
do {
x <- ma ; -- ma :: m a x :: a
y <- mb ; -- mb :: m b y :: b ( with the same m! )
return (foo x y) -- foo x y :: c return (foo x y) :: m c
} -- :: m c
Now, since sequence [getLine, getLine, getLine] :: IO [String], this means your do block belongs in IO.
But you can treat the values in their own right, when you got them:
fGetSeq :: IO ()
fGetSeq = do
inputs <- sequence [getLine, getLine, getLine] -- inputs :: [String]
let vals = fTest inputs
mapM_ print vals
fTest :: [String] -> [Int]
fTest = map (read :: String -> Int)
-- or just
fGetSeq1 = do
inputs <- sequence [getLine, getLine, getLine]
mapM_ print ( fTest inputs )
-- or
fGetSeq2 = do { vals <- fTest <$> sequence [getLine, getLine, getLine] ;
mapM_ print vals } -- vals :: [Int]
-- or even (with redundant parens for clarity)
fGetSeq3 = mapM_ print =<< ( fTest <$> sequence [getLine, getLine, getLine] )
-- = mapM_ print . fTest =<< sequence [getLine, getLine, getLine]
The essence of Monad is the layering of the pure 'Haskell world' calculations in between the potentially impure, 'effectful' computations.
So we already are in the pure Haskell world, on the left hand side of that <-. Again, inputs :: [String]. A pure value.
get a value from the IO domain, into the 'Haskell world'
You use the bind operator: (>>=) :: Monad m => m a -> (a -> m b) -> m b.
If m = IO it looks like: (>>=) :: IO a -> (a -> IO b) -> IO b.
As you can see, the function with type a -> IO b addresses the a without IO.
So given a value in the IO monad, e.g. getLine :: IO String:
getInt :: IO Int
getInt = getLine >>= (\s -> return (read s))
Here, s :: String, read :: String -> Int, and return :: Int -> IO Int.
You can rewrite this using a do-block:
getInt :: IO Int
getInt = do
s <- getLine
return (read s)
Or use the standard library function that does exactly this:
getInt :: IO Int
getInt = readLn
As for your example, you can immediately fix it using a let-binding:
foo :: IO ()
foo = do
input <- sequence [getLine, getLine, getLine]
let ints = bar input
mapM_ print ints
bar :: [String] -> [Int]
bar = map read
Or you can restructure it to use getInt as defined above:
foo :: IO ()
foo = sequence [getInt, getInt, getInt] >>= mapM_ print

How can I get 8-x random values in Haskell?

I'm trying to make a function worp that returns 2 lists of integers.
Where the first list of integers is the result of 8 minus the length of the input list, dice throws.
And the second list is the input list.
This is my code:
import System.Random
worp :: [Int] -> [[IO Int]]
worp d = [werpDobbelstenen (8-length d),d]
werpDobbelstenen :: Int -> [IO Int]
werpDobbelstenen 0 = []
werpDobbelstenen x = randomRIO (1,6):werpDobbelstenen x-1
Im getting this error:
System.IO> :load "X:\\haskell\\dobbel.hs"
ERROR file:.\dobbel.hs:17 - Instance of Num [IO Int] required for definitio of werpDobbelstenen
First, I would return an IO [Int] value for simplicity:
import Control.Monad -- replicateM
import System.Random -- randomRIO
werpDobbelstenen :: Int -> IO [Int]
werpDobbelstenen n = replicateM n (randomRIO (1,6))
Now, define your worp more simply, as one that simply takes a list of Int and returns the desired pair of lists.
worp' :: [Int] -> ([Int], [Int])
worp' d = (d, map (\x -> x - length d) d)
And finally, you can simply map worp over the result of werpDobbelstenen to get an IO ([Int], [Int]) value.
worp :: Int -> IO ([Int], [Int])
worp n = fmap worp' (werpDobbelstenen n)
After a little more thinking, I think this is what you want:
import Control.Monad -- replicateM
import System.Random -- randomRIO
werpDobbelstenen :: Int -> IO [Int]
werpDobbelstenen n = replicateM n (randomRIO (1,6))
worp' :: [Int] -> IO ([Int], [Int])
worp' d = let n = 8 - length d
in do d' <- werpDobbelstenen n
return (d, d')
worp :: Int -> IO ([Int], [Int])
worp n = werpDobbelstenen n >>= worp'
>>> worp 6
([4,1,2,5,6,4],[1,2])
In this case, the second value of the tuple is always an empty list for n >= 8. You may want to do something different for values larger than 8.

String vs Char mismatch in haskell

I'm getting an error about a type mismatch:
Main.hs:47:28:
Couldn't match type ‘[Char]’ with ‘Char’
Expected type: IO Char
Actual type: IO String
In the first argument of ‘liftIO’, namely ‘prompt’
In the second argument of ‘($)’, namely ‘liftIO prompt’
and struggling to understand why an IO Char is expected. Since prompt does type-check as IO String in line 46, and I thought, perhaps mistakenly, that liftIO would turn it to a String as suggested in this answer.
module Main where
import Syntax
import Parser
import Eval
import Pretty
import Counter
import Control.Monad
import Control.Monad.Trans
import System.Console.Haskeline
import Control.Monad.State
showStep :: (Int, Expr) -> IO ()
showStep (d, x) = putStrLn ((replicate d ' ') ++ "=> " ++ ppexpr x)
process :: Counter -> String -> InputT (StateT [String] IO) ()
process c line =
if ((length line) > 0)
then
if (head line) /= '%'
then do
modify (++ [line])
let res = parseExpr line
case res of
Left err -> outputStrLn $ show err
Right ex -> do
let (out, ~steps) = runEval ex
--mapM_ showStep steps
out_ps1 c $ out2iout $ show out
else do
let iout = handle_cmd line
out_ps1 c iout
-- TODO: don't increment counter for empty lines
else do
outputStrLn ""
out2iout :: String -> IO String
out2iout s = return s
out_ps1 :: Counter -> IO String -> InputT (StateT [String] IO) ()
out_ps1 c iout = do
--out <- liftIO iout
let out_count = c 0
let prompt = (getPrompt out_count iout) :: IO String
outputStrLn $ liftIO prompt
outputStrLn ""
getPrompt :: IO Int -> IO String -> IO String
getPrompt ion iout = do
n <- ion
out <- iout
return $ "Out[" ++ (show n) ++ "]: " ++ out
handle_cmd :: String -> IO String
handle_cmd line = if line == "%hist"
then
evalStateT getHist []
else
return "unknown cmd"
joinHist :: IO [String] -> IO String
joinHist ixs = do
xs <- ixs
return $ unlines xs
getHist :: StateT [String] IO String
getHist = do
hist <- lift get
let hists = (zip [(1::Int)..] hist) :: [(Int, String)]
return $ combineHist hists
combineHist :: [(Int, String)] -> String
combineHist hists = unlines $ map (\(i, h) -> show i ++ ": " ++ show h) hists
main :: IO ()
main = do
c <- makeCounter
repl c
repl :: Counter -> IO ()
repl c = evalStateT (runInputT defaultSettings(loop c)) []
loop :: Counter -> InputT (StateT [String] IO) ()
loop c = do
minput <- getLineIO $ in_ps1 $ c
case minput of
Nothing -> return ()
Just input -> process c input >> loop c
getLineIO :: (MonadException m) => IO String -> InputT m (Maybe String)
getLineIO ios = do
s <- liftIO ios
getInputLine s
in_ps1 :: Counter -> IO String
in_ps1 c = do
let ion = c 1
n <- ion
let s = "Untyped: In[" ++ (show n) ++ "]> "
return s
More context can be found here.
You are passing an IO action in place of a String to outputStrLn. You should instead do:
prompt <- liftIO $ getPrompt out_count iout
outputStrLn prompt
to obtain the String from the IO action, using liftIO and then passing this to outputStrLn.

Difference in GHC versions - compile error

I was practicing my Haskell and I came across a weird problem which I was unable to find a solution to on the Internet. I decided to solve this problem:
https://www.hackerrank.com/challenges/fibonacci-fp
In as many ways I can think of. One way is to perform recursion with memoization where I want to use State monad as a cache. I have GHC 7.10.2 on my Windows 10 and GHC 7.6.2 on my Ubuntu 14.04. This code below compiles (and runs very well) on 7.6.2 and doesn't compile on 7.10.2 giving error wherever I type 'Map', for example:
Not in scope: type constructor or class: 'Map.Map'
Not in scope: 'Map.lookup'
module Main (
main
) where
import qualified Data.Map as Map
import Control.Monad.State
type CacheState = Map.Map Int Int
type IOState a = StateT CacheState IO a
modNum :: Int
modNum = 100000007
fibsMod :: [Int]
fibsMod = 0 : 1 : zipWith (\x y -> (x + y) mod modNum ) fibsMod (tail fibsMod)
-- | calculate Fibs with memoization in map
memoizedFib :: Int -> IOState Int
memoizedFib n = do
state <- get
let x = Map.lookup n state
case x of
Just y ->
return y
Nothing -> do
n1 <- memoizedFib (n - 1)
n2 <- memoizedFib (n - 2)
let n3 = mod (n1 + n2) modNum
put (Map.insert n n3 state)
return n3
query :: [Int] -> IOState ()
query [] = return ()
query (n:ns) = do
fibNum <- memoizedFib n
liftIO $ print fibNum
query ns
main :: IO ()
main = do
inputdata <- getContents
let intList = (map (read :: String -> Int) . tail . words) inputdata
evalIOState $ query intList
where
initState :: Int -> Map.Map Int Int
initState upTo = Map.fromList $ zip [0 .. upTo] $ take upTo fibsMod
--initState upTo = Map.fromList $ [(0, 0), (1, 1)]
evalIOState :: IOState a -> IO a
evalIOState m = evalStateT m (initState 10001)
Does anybody know why am I facing this problem? It's very disturbing.
Additional question
As you can see I didn't perform exactly recursion with memoization. However leaving one of those lines uncommented can change approach:
initState upTo = Map.fromList $ zip [0 .. upTo] $ take upTo fibsMod
--initState upTo = Map.fromList $ [(0, 0), (1, 1)]
The problem is that using the second line performs terrible. I don't know where I made a mistake, but I think it should run in linear time with memoization. However with this line my algorithm is clearly exponential (I couldn't even get the answer for 50-th Fib number - that long). What did I do wrong in this case?
UPDATE
Thanks to your comments I fixed my code. Obviously there was a problem with mod function (I completely don't know how did this compile on GHC 7.6.2). Also I changed:
import qualified Data.Map as Map
to:
import qualified Data.Map.Strict as Map
and now this code below works as intended:
module Main (
main
) where
import qualified Data.Map.Strict as Map
import Control.Monad.State
type CacheState = Map.Map Int Int
type IOState a = StateT CacheState IO a
modNum :: Int
modNum = 100000007
fibsMod :: [Int]
fibsMod = 0 : 1 : zipWith (\x y -> (x + y) `mod` modNum) fibsMod (tail fibsMod)
-- | calculate Fibs with memoization in map
memoizedFib :: Int -> IOState Int
memoizedFib n = do
state <- get
let x = Map.lookup n state
case x of
Just y ->
return y
Nothing -> do
n1 <- memoizedFib (n - 1)
n2 <- memoizedFib (n - 2)
state <- get
let n3 = mod (n1 + n2) modNum
put (Map.insert n n3 state)
return n3
query :: [Int] -> IOState ()
query [] = return ()
query (n:ns) = do
fibNum <- memoizedFib n
liftIO $ print fibNum
query ns
main :: IO ()
main = do
inputdata <- getContents
let intList = (map (read :: String -> Int) . tail . words) inputdata
evalIOState $ query intList
where
initState :: Int -> Map.Map Int Int
--initState upTo = Map.fromList $ zip [0 .. upTo] $ take upTo fibsMod
initState upTo = Map.fromList [(0, 0), (1, 1)]
evalIOState :: IOState a -> IO a
evalIOState m = evalStateT m (initState 10001)
So now the question comes down to: Why did I need to use Data.Map.Strict, how is it different and why GHC 7.6.2 didn't need it?

Resources