While loop in Haskell with a condition - loops

I'm having a little Haskell Situation over here. I'm trying to write two functions with monads.
First one is supposed to iterate through a function as long as the condition is true for the input / output of the function. Second one is supposed to use the first one to take a number as input and write it as output until you enter a space.
I'm stuck with this, any help?
module Test where
while :: (a -> Bool) -> (a -> IO a) -> a -> IO a
while praed funktion x = do
f <- praed (funktion x)
if f == True then do
y <- funktion x
while praed funktion y
else return x
power2 :: IO ()
power2 = do putStr (Please enter a number.")
i <- getChar
while praed funktion
where praed x = if x /= ' ' then False else True
funktion = i

import Control.Monad
while :: (a -> Bool) -> (a -> IO a) -> a -> IO a
while praed funktion x
| praed x = do
y <- funktion x
while praed funktion y
| otherwise = return x
power2 :: IO ()
power2 = do
putStr "Please enter a number."
i <- getChar
let praed x = x /= ' '
let f x = do
putChar x
getChar
while praed f '?'
return ()
Some notes:
Using if x then True else False is redundant, it's equivalent to just x.
Similarly if x == True ... is redundant and equivalent to if x ....
You need to distinguish between IO actions and their results. For example, if yo do
do
i <- getChar
...
then in ... i represents the result of the action, a character, so i :: Char. But getChar :: IO Char is the action itself. You can view it as a recipe that returns Char when performed. You can pass the recipe around to functions etc., and it is only performed when executed somewhere.
Your while called funktion twice, which probably isn't what you intend - it would read a character twice, check the first one and return the second one. Remember, your funktion is an action, so each time you "invoke" the action (for example by using <- funktion ... in the do notation), the action is run again. So it should rather be something like
do
y <- funktion x
f <- praed y
-- ...
(My code is somewhat different, it checks the argument that is passed to it.)

For a pure version:
{-# LANGUAGE BangPatterns #-}
while :: (a -> Bool) -> (a -> a) -> a -> a
while p f = go where go !x = if p x then go (f x) else x
test1 :: Int
test1 = while (< 1000) (* 2) 2
-- test1 => 1024
for monadic:
import Control.Monad
whileM :: (Monad m, MonadPlus f) => (a -> m Bool) -> m a -> m (f a)
whileM p f = go where
go = do
x <- f
r <- p x
if r then (return x `mplus`) `liftM` go else return mzero
test2 :: IO [String]
test2 = whileM (return . (/= "quit")) getLine
-- *Main> test2
-- quit
-- []
-- *Main> test2
-- 1
-- 2
-- 3
-- quit
-- ["1","2","3"]
power2 :: IO (Maybe Char)
power2 = whileM (return . (/= 'q')) getChar
-- *Main> power2
-- q
-- Nothing
-- *Main> power2
-- 1
-- 2
-- 3
-- q
-- Just '\n'
see also:
http://hackage.haskell.org/package/monad-loops, http://hackage.haskell.org/package/loop-while, http://hackage.haskell.org/package/control-monad-loop.
http://www.haskellforall.com/2012/01/haskell-for-c-programmers-for-loops.html

Related

Haskell: looping over user input gracefully

This is an example from Learn You a Haskell:
main = do
putStrLn "hello, what's your name?"
name <- getLine
putStrLn ("Hey, " ++ name ++ ", you rock!")
The same redone without do for clarity:
main =
putStrLn "hello, what's your name?" >>
getLine >>= \name ->
putStrLn $ "Hey, " ++ name ++ ", you rock!"
How am I supposed to loop it cleanly (until "q"), the Haskell way (use of do discouraged)?
I borrowed this from Haskell - loop over user input
main = mapM_ process . takeWhile (/= "q") . lines =<< getLine
where process line = do
putStrLn line
for starters, but it won't loop.
You can call main again and check if your string is "q" or not.
import Control.Monad
main :: IO ()
main =
putStrLn "hello, what's your name?" >>
getLine >>= \name ->
when (name /= "q") $ (putStrLn $ "Hey, " ++ name ++ ", you rock!") >> main
λ> main
hello, what's your name?
Mukesh Tiwari
Hey, Mukesh Tiwari, you rock!
hello, what's your name?
Alexey Orlov
Hey, Alexey Orlov, you rock!
hello, what's your name?
q
λ>
May be you can also use laziness on IO type by adapting the System.IO.Lazy package. It basically includes only run :: T a -> IO a and interleave :: IO a -> T a functions to convert IO actions into lazy ones back and forth.
import qualified System.IO.Lazy as LIO
getLineUntil :: String -> IO [String]
getLineUntil s = LIO.run ((sequence . repeat $ LIO.interleave getLine) >>= return . takeWhile (/=s))
printData :: IO [String] -> IO ()
printData d = d >>= print . sum . map (read :: String -> Int)
*Main> printData $ getLineUntil "q"
1
2
3
4
5
6
7
8
9
q
45
In the above code we construct an infinite list of lazy getLines by repeat $ LIO.interleave getLine of type [T String] and by sequence we turn it into T [String] type and proceed reading up until "q" is received. The printData utility function is summing up and printing the entered integers.

I/O Loop in Haskell

I am currently working on this Haskell problem and I seem to be stuck.
Write a function, evalpoly, that will ask a user for the degree of a single variable polynomial, then read in the coefficients for the polynomial (from highest power to lowest), then for a value, and will output the value of the polynomial evaluated at that value. As an example run:
> evalpoly
What is the degree of the polynomial: 3
What is the x^3 coefficient: 1.0
What is the x^2 coefficient: - 2.0
What is the x^1 coefficient: 0
What is the x^0 coefficient: 10.0
What value do you want to evaluate at: -1.0
The value of the polynomial is 7.0
As of now, I have this:
evalpoly :: IO ()
evalpoly = putStr "What is the degree of the polynomial: " >>
getLine >>= \xs ->
putStr "What is the x^" >>
putStr (show xs) >>
putStr " coefficient: " >>
putStrLn ""
How would I go about adding the loop and calculations?
Warning:
I spoil this completely so feel free to stop at any point and try to go on yourself
Instead of pushing it all into this single function I will instead break this down into smaller tasks/functions.
So let's start with this.
1. Input
On obvious part is to ask for an value - and if we are on it we can make sure that the user input is any good (I am using Text.Read.readMaybe for this:
query :: Read a => String -> IO a
query prompt = do
putStr $ prompt ++ ": "
val <- readMaybe <$> getLine
case val of
Nothing -> do
putStrLn "Sorry that's a wrong value - please reenter"
query prompt
Just v -> return v
please note that I appended the ": " part already so you don't have to do this for your prompts
having this all the questions to your user become almost trivial:
queryDegree :: IO Int
queryDegree = query "What is the degree of the polynomial"
queryCoef :: Int -> IO (Int, Double)
queryCoef i = do
c <- query prompt
return (i,c)
where prompt = "What is the x^" ++ show i ++ " coefficient"
queryPoint :: IO Double
queryPoint = query "What value do you want to evaluate at"
please note that I provide the powers together with the coefficients - this make the calculation a bit easier but is not strictly necessary here I guess (you could argue that this is more than the function should do at this point and later use zip to get the powers too)
Asking all the inputs is now really easy once you've seen mapM and what it can do - it's the point where you usually would want to write a loop:
queryPoly :: IO [(Int, Double)]
queryPoly = do
n <- queryDegree
mapM queryCoef [n,n-1..0]
2. Evaluation
Do evaluate this I just need to evaluate each term at the given point (that is each power, coefficient pair in the list) - which you can do using map - after we just need to sum this all up (sum can do this):
evaluate :: Double -> [(Int, Double)] -> Double
evaluate x = sum . map (\ (i,c) -> c*x^i)
3. Output
Is rather boring:
presentResult :: Double -> IO ()
presentResult v = putStrLn $ "The vaule of the polynomial is " ++ show v
4. Getting it all together
I just have to ask for the inputs, evaluate the value and then present it:
evalpoly :: IO ()
evalpoly = do
p <- queryPoly
x <- queryPoint
presentResult $ evaluate x p
5. Test-Run
Here is an example run
What is the degree of the polynomial: 3
What is the x^3 coefficient: 1.0
What is the x^2 coefficient: -2.0
What is the x^1 coefficient: Hallo
Sorry that's a wrong value - please reenter
What is the x^1 coefficient: 0
What is the x^0 coefficient: 10.0
What value do you want to evaluate at: -1.0
The vaule of the polynomial is 7.0
complete Code
Note that I like to enter the no-buffering because I run into trouble on Windows occasionally if I don't have it - you probably can live without
module Main where
import Control.Monad (mapM)
import Text.Read (readMaybe)
import System.IO (BufferMode(..), stdout, hSetBuffering)
query :: Read a => String -> IO a
query prompt = do
putStr $ prompt ++ ": "
val <- readMaybe <$> getLine
case val of
Nothing -> do
putStrLn "Sorry that's a wrong value - please reenter"
query prompt
Just v -> return v
queryDegree :: IO Int
queryDegree = query "What is the degree of the polynomial"
queryCoef :: Int -> IO (Int, Double)
queryCoef i = do
c <- query prompt
return (fromIntegral i,c)
where prompt = "What is the x^" ++ show i ++ " coefficient"
queryPoint :: IO Double
queryPoint = query "What value do you want to evaluate at"
queryPoly :: IO [(Int, Double)]
queryPoly = do
n <- queryDegree
mapM queryCoef [n,n-1..0]
evaluate :: Double -> [(Int, Double)] -> Double
evaluate x = sum . map (\ (i,c) -> c*x^i)
presentResult :: Double -> IO ()
presentResult v = putStrLn $ "The vaule of the polynomial is " ++ show v
evalpoly :: IO ()
evalpoly = do
p <- queryPoly
x <- queryPoint
presentResult $ evaluate x p

haskell FFI passing array of C structs in and out

I am trying to perform a series of transforms on graphical files using Haskell and Repa/DevIL. The starting example used was provided by the Haskell wiki page https://wiki.haskell.org/Numeric_Haskell:_A_Repa_Tutorial. I am an imperative programmer of 30 years experience with some erlang for good measure, trying to learn Haskell outside a classroom environment.
The problem is manipulating the data after the file load was first transformed into a Repa array:
import Data.Array.Repa.IO.DevIL (runIL,readImage,writeImage,Image(RGB),IL)
import qualified Data.Array.Repa as R
import Data.Vector.Unboxed as DVU
import Control.Monad
main :: IO ()
main = do
[f] <- getArgs
(RGB a) <- runIL $ Data.Array.Repa.IO.DevIL.readImage f
let
c = (computeP (R.traverse a id rgbTransform)) :: IL (Array U DIM3 Float)
which is successfully cast to type "Array F DIM3 Float" as output from the rgbTransform. From that point on it has been a nightmare to use the data. Flicking the array storage type between F(oreign) and U(nboxed) changes all following call's usability, plus the Repa-added monad layer IL forces use of liftM for nearly every equation following the 1st transform:
let -- continued
sh = liftM R.extent c -- IL DIM3
v = liftM R.toUnboxed c -- IL (Vector Float)
lv = liftM DVU.length v -- IL Int
f = liftM indexed v -- vector of tuples: (Int,a) where Int is idx
k = (Z :. 2) :. 2 :. 0 :: DIM3
These are the routines I can call without error. The IO monad's print command produces no output if placed in or after this 'let' list, due to the IL monad layer.
The game plan for the curious:
read the graphic file (done, via Repa)
resize image (not done, no resize in Repa, must be hand-coded)
transform and convert image from Word8 to Float (done)
get a Stablepointer to the transformed Float data (not done)
transform in-place the Float data as an array of C structs
of {Float a,b,c;}, by an external C routine via FFI (not completely
done). This is done hopefully without marshalling a new graphic
array by passing a pointer to the data
perform more passes over the transformed data to extract more info (partly done).
I am looking for help with issues 4 and 5.
4 -> The type system has been difficult to deal with while attempting to get C-usable memory pointers. Going thru the mountains of haskell library calls has not helped.
5 -> The external C routine is of type:
foreign import ccall unsafe "transform.h xform"
c_xform :: Ptr (CFloat,CFloat,CFloat) ->
CInt ->
IO ()
The Ptr is expected to point to an unboxed flat C array of rgb_t structs:
typedef struct
{
float r;
float g;
float b;
} rgb_t;
Available web-based FFI descriptions of how to deal with array pointers in FFI are non-existent if not downright obscure. The fairly straightforward idea of unfreezing and passing in a C array of floating-point RGB structs, modifying them in-place and then freezing the result is what I had in mind. The external transform is pure in the sense that the same input will produce predictable output, does not use threads, does not use global vars nor depend upon obscure libraries.
Foreign.Marshal.Array seems to provide a way to convert haskell data to C data and other way around.
I tested interfacing C code and haskell using the following files (Haskell + FFI for the first time for me)
hsc2hs rgb_ffi.hsc
ghc main.hs rgb_ffi.hs rgb.c
rgb.h
#ifndef RGB_H
#define RGB_H
#include <stdlib.h>
typedef struct {
float r;
float g;
float b;
} rgb_t;
void rgb_test(rgb_t * rgbs, ssize_t n);
#endif
rgb.h
#include <stdlib.h>
#include <stdio.h>
#include "rgb.h"
void rgb_test(rgb_t * rgbs, ssize_t n)
{
int i;
for(i=0; i<n; i++) {
printf("%.3f %.3f %.3f\n", rgbs[i].r, rgbs[i].g, rgbs[i].b);
rgbs[i].r *= 2.0;
rgbs[i].g *= 2.0;
rgbs[i].b *= 2.0;
}
}
rgb_ffi.hsc
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE CPP #-}
module RGB where
import Foreign
import Foreign.C
import Control.Monad (ap)
#include "rgb.h"
data RGB = RGB {
r :: CFloat, g :: CFloat, b :: CFloat
} deriving Show
instance Storable RGB where
sizeOf _ = #{size rgb_t}
alignment _ = alignment (undefined :: CInt)
poke p rgb_t = do
#{poke rgb_t, r} p $ r rgb_t
#{poke rgb_t, g} p $ g rgb_t
#{poke rgb_t, b} p $ b rgb_t
peek p = return RGB
`ap` (#{peek rgb_t, r} p)
`ap` (#{peek rgb_t, g} p)
`ap` (#{peek rgb_t, b} p)
foreign import ccall "rgb.h rgb_test" crgbTest :: Ptr RGB -> CSize -> IO ();
rgbTest :: [RGB] -> IO [RGB]
rgbTest rgbs = withArray rgbs $ \ptr ->
do
crgbTest ptr (fromIntegral (length rgbs))
peekArray (length rgbs) ptr
rgbAlloc :: [RGB] -> IO (Ptr RGB)
rgbAlloc rgbs = newArray rgbs
rgbPeek :: Ptr RGB -> Int -> IO [RGB]
rgbPeek rgbs l = peekArray l rgbs
rgbTest2 :: Ptr RGB -> Int -> IO ()
rgbTest2 ptr l =
do
crgbTest ptr (fromIntegral l)
return ()
main.hs
module Main (main) where
import RGB
main =
do
let a = [RGB {r = 1.0, g = 1.0, b = 1.0},
RGB {r = 2.0, g = 2.0, b = 2.0},
RGB {r = 3.0, g = 3.0, b = 3.0}]
let l = length a
print a
-- b <- rgbTest a
-- print b
c <- rgbAlloc a
rgbTest2 c l
rgbTest2 c l
d <- rgbPeek c l
print d
return ()

`forever`: How to forward information to next iteration?

There is a thread waiting for new input in a queue to safe it to the file system. It also creates backup copies. The sscce looks like this:
import Control.Concurrent
import Control.Concurrent.STM
import Control.Monad
import Data.Time.Clock.POSIX
main :: IO ()
main = do
contentQueue <- atomically $ newTQueue
_ <- forkIO $ saveThreadFunc contentQueue
forever $ do
line <- getLine
atomically $ writeTQueue contentQueue line
saveThreadFunc :: TQueue String -> IO ()
saveThreadFunc queue = forever $ do
newLine <- atomically $ readTQueue queue
now <- round `fmap` getPOSIXTime :: IO Int
writeFile "content.txt" newLine
-- todo: Backup no more than once every 86400 seconds (24 hours).
backupContent now newLine
backupContent :: Int -> String -> IO ()
backupContent t = writeFile $ "content.backup." ++ show t
Now it would be great if the backup would not be written more than once every 24 hours. In imperative programming I would probably use a mutable int lastBackupTime inside the "forever loop" in saveThreadFunc. How can the same effect be achieved in Haskell?
How about Control.Monad.Loops.iterateM_? This is slightly neater as it avoids explict recursion.
iterateM_ :: Monad m => (a -> m a) -> a -> m b
saveThreadFunc :: TQueue String -> Int -> IO ()
saveThreadFunc queue = iterateM_ $ \lastBackupTime -> do
newLine <- atomically $ readTQueue queue
now <- round `fmap` getPOSIXTime :: IO Int
writeFile "content.txt" newLine
let makeNewBackup = now >= lastBackupTime + 86400
when makeNewBackup (backupContent now newLine)
return (if makeNewBackup then now else lastBackupTime)
Replace forever with explicit recursion.
foo :: Int -> IO ()
foo n = do
use n
foo (n+1)
Of course, you can use any type for your state instead of Int.
Otherwise, if you really want the mutable state:
foo :: IO ()
foo = do
r <- newIORef (0 :: Int)
forever $ do
n <- readIORef r
use n
writeIORef r (n+1)
Unless you really need mutability for some other reason, I'd not recommend the second option.
Adapting the above idea to the concrete code:
saveThreadFunc :: Int -> TQueue String -> IO ()
saveThreadFunc lastBackupTime queue = do
newLine <- atomically $ readTQueue queue
now <- round `fmap` getPOSIXTime :: IO Int
writeFile "content.txt" newLine
let makeNewBackup = now >= lastBackupTime + 86400
if makeNewBackup then do
backupContent now newLine
saveThreadFunc now queue
else
saveThreadFunc lastBackupTime queue
The usual way to add state to a monad is using StateT from Control.Monad.Trans.State.Strict in the transformers package (part of the Haskell Platform). In this case, you would change the type of saveThreadFunc:
saveThreadFunc :: TQueue String -> StateT Int IO ()
You'd have to Control.Monad.Trans.lift the actual IO things to StateT Int IO, and then in the end evalStateT to turn the whole thing into IO a.
This approach is perhaps more modular than the the iterateM_ one Tom Ellis suggests (although that's something of a matter of taste), and will generally be optimized better than the IORef version chi suggests you avoid.

How to read a file into Vector of Doubles?

I have a name of a file (as a string), and that file contains certain amount (1000000, for example) double-precision floating-point values (stored as binary, 8 bytes for each, obviously).
What would be the best way to read those doubles into a vector?
Here's how I did it in the end:
import qualified Data.Vector.Unboxed as V
import qualified Data.Vector.Unboxed.Mutable as VM
import qualified Data.ByteString.Lazy as BS
import Data.Binary
import Data.Binary.Get
import System.IO.Unsafe (unsafePerformIO)
import Unsafe.Coerce
readDoubles :: Int -> FilePath -> IO (V.Vector Double)
readDoubles n f = BS.readFile f >>= return . runGet (getVector n)
getVector :: Int -> Get (V.Vector Double)
{-# INLINE getVector #-}
getVector n = do
mv <- liftGet $ VM.new n
let fill i
| i < n = do
x <- fmap unsafeCoerce getWord64be
(unsafePerformIO $ VM.unsafeWrite mv i x) `seq` return ()
fill (i+1)
| otherwise = return ()
fill 0
liftGet $ V.unsafeFreeze mv
liftGet :: IO b -> Get b
liftGet = return . unsafePerformIO

Resources