Monad transformer – Explicit lifting - monads

I'm reading about monad transformers in Real World Haskell. In the following example, the stack is Writer on top State on top of Reader on top of IO.
{-# Language GeneralizedNewtypeDeriving #-}
import Control.Monad
import Control.Monad.State
import Control.Monad.Reader
import Control.Monad.Writer
import System.Directory
import System.FilePath
data AppConfig = AppConfig {
cfgMaxDepth :: Int
} deriving Show
data AppState = AppState {
stDeepestReached :: Int
} deriving Show
newtype MyApp a = MyA {
runA :: WriterT [(FilePath,Int)] (StateT AppState (ReaderT AppConfig IO)) a
} deriving (Monad, MonadIO, Functor, MonadReader AppConfig,
MonadWriter [(FilePath,Int)], MonadState AppState)
runApp :: MyApp a -> Int -> IO ([(FilePath,Int)], AppState)
runApp k maxDepth = let config = AppConfig maxDepth
state' = AppState 0
in runReaderT (runStateT (execWriterT $ runA k) state') config
constrainedCount :: Int -> FilePath -> MyApp ()
constrainedCount curDepth path = do
contents <- liftIO . getDirectoryContents $ path
cfg <- ask
let maxDepth = cfgMaxDepth cfg
tell [(path,curDepth)]
forM_ (filter (\d' -> d' /= ".." && d' /= ".") contents) $ \d -> do
let newPath = path </> d
isDir <- liftIO $ doesDirectoryExist newPath
when (isDir && curDepth < maxDepth) $ do
let newDepth = curDepth+1
st <- get
when (stDeepestReached st < newDepth) $
put st { stDeepestReached = newDepth }
constrainedCount newDepth newPath
main = runApp (constrainedCount 0 "/tmp") 2 >>= print
I (think I) understand how I can simply call ask, get and put since these are defined in the MonadReader, MonadWriter and MonadState typeclasses and there are instances such as MonadWriter (StateT s m) and so on.
What I don't understand is why I cannot explicit lift an action from the layer below up to the current monad transformer. In constrainedCount I'm in the Reader monad, if I understand correctly, and I thought both st <- get and st <- lift get should work. (And that tell and lift . lift . tellshould be the same). If I changest <- gettost <- lift get` I get the error
Couldn't match type `t0 m0' with `MyApp'
Expected type: MyApp ()
Actual type: t0 m0 ()
which tells me very little... Is my understanding of this completely wrong?

Let's have a look at the type of lift get:
lift get :: (MonadTrans t, MonadState a m) => t m a
But your MyApp isn't a monad transformer, it's only a monad. But what's inside is, of course, so if you use
st <- MyA $ lift get
it works.

Related

Is it possible to bypass the signature of a module for debugging purpose?

I try to understand a strange behaviour of some functions of a module that rely on a variable of this module masked by the signature of this module. I would like to print this variable at some points of the program, but since it is masked, I do not known how to access it.
Moreover, this module is part of a big project that I do not want to modify and recompile myself.
Is it possible to access this variable for debugging purposes ? Even doing temporarily dirty things ?
EDIT: here some representative code
module type S = sig val f : unit -> unit end
module M : S = struct let x = ref 0 let f () = Format.printf "%d#." !x; incr x end
How to access M.x ?
Of course you can!
First, you can just hide the signature for a while :
module type S = sig val f : unit -> unit end
module M (* : S *) = struct
let x = ref 0
let f () = Format.printf "%d#." !x; incr x
end
Or you can show x in the signature :
module type S = sig
val x : int ref
val f : unit -> unit
end
module M : S = struct
let x = ref 0
let f () = Format.printf "%d#." !x; incr x
end
As you prefer. In both cases, M.x will be available outside the module.
You can even define a function print_x like this :
module type S = sig
val print_x : unit -> unit
val f : unit -> unit
end
module M : S = struct
let x = ref 0
let print_x () = Format.printf "%d#." !x
let f () = Format.printf "%d#." !x; incr x
end
and use M.print_x () wherever you want.

Mocking IO Actions: getArgs and putStrLn

I'm trying to test a small function (or rather, IO Action) that takes a command line argument and outputs it to the screen. My original (untestable) function is:
-- In Library.hs
module Library where
import System.Environment (getArgs)
run :: IO ()
run = do
args <- getArgs
putStrLn $ head args
After looking at this answer about mocking, I have come up with a way to mock getArgs and putStrLn by using a type class constrained type. So the above function becomes:
-- In Library.hs
module Library where
class Monad m => SystemMonad m where
getArgs :: m [String]
putStrLn :: String -> m ()
instance SystemMonad IO where
getArgs = System.Environment.getArgs
putStrLn = Prelude.putStrLn
run :: SystemMonad m => m ()
run = do
args <- Library.getArgs
Library.putStrLn $ head args
This Library., Prelude. and System.Environment. are to avoid compiler complaints of Ambigious Occurence. My test file looks like the following.
-- In LibrarySpec.hs
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE FlexibleInstances #-}
import Library
import Test.Hspec
import Control.Monad.State
data MockArgsAndResult = MockArgsAndResult [String] String
deriving(Eq, Show)
instance SystemMonad (State MockArgsAndResult) where
getArgs = do
MockArgsAndResult args _ <- get
return args
putStrLn string = do
MockArgsAndResult args _ <- get
put $ MockArgsAndResult args string
return ()
main :: IO ()
main = hspec $ do
describe "run" $ do
it "passes the first command line argument to putStrLn" $ do
(execState run (MockArgsAndResult ["first", "second"] "")) `shouldBe` (MockArgsAndResult ["first", "second"] "first")
I'm using a State monad that effectively contains 2 fields.
A list for the command line arguments where the mock getArgs reads from
A string that the mock putStrLn puts what was passed to it.
The above code works and seems to test what I want it to test. However, I'm wondering if there is some better / cleaner / more idiomatic way of testing this. For one thing, I'm using the same state to both put stuff into the test (my fake command line arguments), and then get stuff out of it (what was passed to putStrLn.
Is there a better way of doing what I'm doing? I'm more familiar with mocking in a Javascript environment, and my knowledge of Haskell is pretty basic (I arrived at the above solution by a fair bit of trial and error, rather than actual understanding)
The better way is to avoid needing to provide mock versions of getArgs and putStrLn by separating out the heart of the computation into a pure function.
Consider this example:
main = do
args <- getArgs
let n = length $ filter (\w -> length w < 5) args
putStrLn $ "Number of small words: " ++ show n
One could say that the heart of the computation is counting the number of small words which is a pure function of type [String] -> Int. This suggest that we should refactor the program like this:
main = do
args <- getArgs
let n = countSmallWords args
putStrLn $ "Number of small words: " ++ show n
countSmallWords :: [String] -> Int
countSmallWords ws = ...
Now we just test countSmallWords, and this is easy because it is pure function.

How to filter a list with another mutable vector in haskell

I am new to Haskell. I want to implement the following python program in Haskell.
a = [1,2,3,6,7,12,45,54,2,12,10]
b = [1,2,3,6,7,8]
c = [ i for i in b if a[i] % 2 == 0 ]
print c
I want a be a Data.Vector.Mutable in Haskell.
So I write something like
let a1 = fromList ([1,2,3,6,7,12,45,54,2,12,10] :: [Int])
let b = [1,2,3,6,7,8]
let c = [ i | i <- b, filter i a1 ]
print c
However I have no idea about how to implement filter .
I know I should x <- thaw a1 and y <- read x i then check y.
But how to assemble them together?
Lets assume that a :: MVector s Int, b :: [Int] and your result should be c :: m [Int], where m is some monad, as we're using a mutable vector. Now, all we need is a fitting predicate:
-- evenVM :: PrimMonad m => MVector (PrimState m) Int -> Int -> m Bool
evenVM v i = do
if (M.length v) < i || i <= 0
then return False
else fmap even $ M.read v (i - 1)
evenVM a has type PrimMonad m => Int -> m Bool. As such, it can be used together with filterM (from Control.Monad), since every PrimMonad is also a Monad:
c = filterM (evenVM a) b
thaw isn't necessary if a really is a mutable vector. If a is a non-mutable vector, you can use filter and almost the same approach as above.
You have to use Vector's zip to index the elements and filter them accordingly.
import Data.Vector
import Prelude hiding(zip, filter, elem, map, length)
main :: IO ()
main = do
let a = fromList [1,2,3,6,7,12,45,54,2,12,10]
let a' = fromList [0..(length a)]
let b = fromList [1,2,3,6,7,8]
let c = map snd $ filter (\(x,y) -> (y `elem` b) && x `mod` 2 == 0) (zip a a')
print c
In ghci:
ghci > main
fromList [1,3,7,8]
You can use filter in conjunction with map.
let a = [1,2,3,6,7,12,45,54,2,12,10]
b = [1,2,3,6,7,8] :: [Int]
in filter even $ map (a !!) b
If you need this from Vector you can add a couple of fromList:
import qualified Data.Vector V
let a = V.fromList [1,2,3,6,7,12,45,54,2,12,10]
b = V.fromList ([1,2,3,6,7,8] :: [Int])
in V.filter even $ V.map (a V.!) b
And if you prefer the monadic version:
do
a <- V.fromList [1,2,3,6,7,12,45,54,2,12,10]
b <- V.fromList ([1,2,3,6,7,8] :: [Int])
V.filter even (return (a V.! b))

iterate list creation from IO Int, How to?

I am playing with linkedlist problem in python challenge that require querying a next value (guess it be Int).
I create function for get the next value as follows
url = "http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing="
getNext :: Int -> IO Int
getNext x = do
rsp <- simpleHTTP (getRequest $ url ++ show x)
bdy <- getResponseBody rsp
let num = last $ splitWhen (==' ') bdy
return (read num::Int)
and it work fine (in ghci)
> getNext 12345
44827
> getNext 44827
45439
While I suppose to repeatedly call getNext until I found the answer, I think I should keep the history like I can do in non-monadic world so I can continue from the last value in case something fail.
> let nX x = x + 3
> :t nX
nX :: Num a => a -> a
> take 10 $ iterate nX 1
[1,4,7,10,13,16,19,22,25,28]
I think it should be a monadic lifted version of iterate and found iterateM_ from Control.Monad.Loops but it didn't work as I expected. There is nothing shown (I think _ suffix mean discard the result but there is no iterateM)
> :t iterate
iterate :: (a -> a) -> a -> [a]
> :t iterateM_
iterateM_ :: Monad m => (a -> m a) -> a -> m b
Question is how can I get [Int] as in non-monadic iteration. I think I want a function that return IO [Int] to be able to pull-out and filter/process in my code like this
main = do
i <- getAllList
let answer = last i -- or could be a repeated converged value, don't know yet
putStrLn (show answer)
getAllList :: IO [Int]
If you want your function to terminate early, rather than give back an
infinite list of results, you will want to use unfoldrM rather than
iterateM. This can be done with something like the following:
url = "http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing="
start = 12345
stop = 10000
shouldStop :: Int -> Bool
shouldStop x = x == stop
getNext :: Int -> IO (Maybe (Int, Int))
getNext prev
| shouldStop prev = return Nothing
| otherwise = do
rsp <- simpleHTTP (getRequest $ url ++ show prev)
bdy <- getResponseBody rsp
let num = read $ last $ splitWhen (==' ') bdy :: Int
print (prev, num)
return $ Just (num, num)
getAllList :: IO [Int]
getAllList = unfoldrM getNext start
This will allow you to define a stopping criteria so that the loop can
terminate, but you will not receive results back until the termination
criteria has been met.
The unfoldrM function can be found in the monad-loops package, but the
latest version keeps reusing the original seed rather than the one produced by
the generator function (I believe this has been fixed but not uploaded to
Hackage). This is the version of unfoldrM that you would want.
-- |See 'Data.List.unfoldr'. This is a monad-friendly version of that.
unfoldrM :: (Monad m) => (a -> m (Maybe (b,a))) -> a -> m [b]
unfoldrM = unfoldrM'
-- |See 'Data.List.unfoldr'. This is a monad-friendly version of that, with a
-- twist. Rather than returning a list, it returns any MonadPlus type of your
-- choice.
unfoldrM' :: (Monad m, MonadPlus f) => (a -> m (Maybe (b,a))) -> a -> m (f b)
unfoldrM' f z = go z
where go z = do
x <- f z
case x of
Nothing -> return mzero
Just (x, z) -> do
xs <- go z
return (return x `mplus` xs)
This is how you might go about this using Pipes, which will allow you to
do the processing as a stream of results without resorting to lazy I/O.
import Network.HTTP
import Control.Monad
import Data.List.Split
import Control.Monad
import Control.Proxy
url = "http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing="
grabber :: (Proxy p) => Int -> () -> Producer p String IO ()
grabber start () = runIdentityP $ loop $ show start where
loop x = do
-- Grab the next value
x' <- lift $ getNext x
-- Send it down stream
respond x'
-- Keep grabbing
loop x'
-- Just prints the values recieved from up stream
printer :: (Proxy p, Show a) => () -> Consumer p a IO r
printer () = runIdentityP $ forever $ do
a <- request () -- Consume a value
lift $ putStrLn $ "Received a value: " ++ show a
getNext :: String -> IO String
getNext prev = do
rsp <- simpleHTTP (getRequest $ url ++ prev)
bdy <- getResponseBody rsp
let num = last $ splitWhen (== ' ') bdy
return num
main = runProxy $ grabber start >-> printer
So what you want is basically
iterateM :: Monad m => (a -> m a) -> a -> m [a]
iterateM action a = do
a' <- action a
liftM (a':) $ iterateM action a'
The problem is that this doesn't work lazily as one might expect: since the monadic bind is strict, you're stuck in an infinite loop, even if you only want to evaluate a finite number of as.

forcing a list to be recomputed

The function search below searches for two inputs which have the same output under some function. During the search it iterates over the input list xs twice, and this input list could be very large, e.g. [0..1000000000]. I'd rather use memory for storing the HashSet created by collision rather than storing the elements of xs, and my understanding is that even though xs could be lazily computed it would be kept around in case it was needed for the call to find.
Questions:
is this understanding correct?
if I keep it as a list is there a way I can have xs recomputed if it is passed to find?
is there an alternative data structure I can use for xs which allows me to control the space used? xs is just used to specify which inputs to check.
Note that there are no type restrictions on xs - it can be a collection of any type.
import Data.HashSet as Set
import Data.Hashable
import Data.List
search :: (Hashable b, Eq b) => (a->b) -> [a] -> Maybe (a,a)
search h xs =
do x0 <- collision h xs
let h0 = h x0
x1 <- find (\x -> (h x) == h0) xs
return (x0,x1)
collision :: (Hashable b, Eq b) => (a->b) -> [a] -> Maybe a
collision h xs = go Set.empty xs
where
go s [] = Nothing
go s (x:xs) =
if y `Set.member` s
then Just x
else go (Set.insert y s) xs
where y = h x
main = print $ search (\x -> x `mod` 21) ([10,20..2100] :: [Int])
I answered basically this question here: https://stackoverflow.com/a/6209279/371753
Here's the relevant code.
import Data.Stream.Branching(Stream(..))
import qualified Data.Stream.Branching as S
import Control.Arrow
import Control.Applicative
import Data.List
data UM s a = UM (s -> Maybe a) deriving Functor
type UStream s a = Stream (UM s) a
runUM s (UM f) = f s
liftUM x = UM $ const (Just x)
nullUM = UM $ const Nothing
buildUStream :: Int -> Int -> Stream (UM ()) Int
buildUStream start end = S.unfold (\x -> (x, go x)) start
where go x
| x < end = liftUM (x + 1)
| otherwise = nullUM
usToList x = unfoldr (\um -> (S.head &&& S.tail) <$> runUM () um) x
Long story short, instead of passing around a list, pass around a data type that describes how to generate a list. Now you can write functions directly over the stream, or you can use the usToList function to use the list functions you already have.