onegun
onegun

Reputation: 803

haskell foldl with output

i am parsing a string for example "xxxxyzz", so if the char is "x" then i will need to do a output and make changes to the list at the same time. The code below is

import Data.Char
output l = zipWith (+) rr ll
            where
              out = foldl
                        ( \ (c,a) e ->
                               case c of
                                'x' -> chr c!!0 --output first element of the list
                                       ([1]++tail(c),a) ) -- add [1] to the c list
                        ([0,0,0,0,0],[0,0,0,0,0])
              (ll,rr) = out l 

Upvotes: 0

Views: 309

Answers (2)

ljedrz
ljedrz

Reputation: 22193

In Haskell you can't predict the order of execution without using monads. For starters you may want to try to do some testing in the do block of main and then rewrite it as a separate function.

You may want to familiarize yourself with the concept of IO in Haskell: http://www.haskell.org/onlinereport/haskell2010/haskellch7.html#x14-1420007

Upvotes: 0

josejuan
josejuan

Reputation: 9566

You can write (not recommended) some like

output'' :: String -> IO String
output'' = fmap reverse . foldM parseChar []
  where parseChar xs 'x' = putStrLn "'x' to upper" >> return ('X':xs)
        parseChar xs 'y' = putStrLn "'y' to 'W'"   >> return ('W':xs)
        parseChar xs  x  = putStrLn "no transform" >> return ( x :xs)

with output

*Main> output'' "xyz"
'x' to upper
'y' to 'W'
no transform
"XWz"

But, from For a Few Monads More (Learn You a Haskell for Great Good!)

You can write some like:

import Control.Monad.Writer

output :: String -> Writer [String] String
output [] = return []
output (x:xs) = do
  xs' <- output xs
  x'  <- case x of
         'x' -> tell ["'x' to upper"] >> return 'X'
         'y' -> tell ["'y' to 'W'"]   >> return 'W'
         _   -> tell ["no transform"] >> return x
  return (x':xs')

using monads is more flexible and using Writer do your code pure (is pure and you have control about how process monadic context and data; not in direct IO output'' function).

You can use output function into impure code as

main = do
  input <- getLine
  let (result, logging) = runWriter $ output input
  putStrLn $ "Result: " ++ result
  putStrLn $ unlines logging

a running output could be

*Main> main
hxdynx
Result: hXdWnX
'x' to upper
no transform
'y' to 'W'
no transform
'x' to upper
no transform

you can combine monad with monadic functions like "foldM", some like

output' :: String -> Writer [String] String
output' = fmap reverse . foldM parseChar []
  where parseChar xs 'x' = tell ["'x' to upper"] >> return ('X':xs)
        parseChar xs 'y' = tell ["'y' to 'W'"]   >> return ('W':xs)
        parseChar xs  x  = tell ["no transform"] >> return ( x :xs)

(log array are reversed)

Upvotes: 1

Related Questions