How to define a state monad? - haskell

I want to define a State monad that manages errors (in a sense like Maybe): if an error/problem occurs during the "do" computation, it is signal led and propagated by >>=.
The error should also contain a string describing it.
After, i want to apply this monad to mapTreeM, using for map a function that assumes states as numbers and a tree containing numbers, and at each visiting step updates the current state by adding to it the value of the current leaf; the resulting tree must contain a pair with the old leaf value and the state at the visiting instant. Such visit must fail if the state becomes negative during the computation, and succeed if it is positive.
e.g. Given this tree: Branch (Branch (Leaf 7) (Branch (Leaf (-1)) (Leaf 3))) (Branch (Leaf (-2)) (Leaf 9))
We obtain a tree (considering the initial state 0): Branch (Branch (Leaf (7,7)) (Branch (Leaf (-1,6)) (Leaf (3,9)))) (Branch (Leaf (-2,7)) (Leaf (9,16)))
If we put -18 in the second leaf, we should obtain an erroneous value signaling that we reached a negative state (-11).
I did a thing like this to print the tree without managing errors...i haven't understood how to do it.
The following is my code:
module Main where
-- State monad
newtype State st a = State (st -> (st, a))
instance Monad (State state) where
return x = State(\s -> (s,x))
State f >>= g = State(\oldstate ->
let (newstate, val) = f oldstate
State newf = g val
in newf newstate)
-- Recursive data structure for representing trees
data Tree a = Leaf a | Branch (Tree a) (Tree a)
deriving (Show,Eq)
-- Utility methods
getState :: State state state
getState = State(\state -> (state,state))
putState :: state -> State state ()
putState new = State(\_ -> (new, ()))
mapTreeM :: (Num a) => (a -> State state b) -> Tree a -> State state (Tree b)
mapTreeM f (Leaf a) =
f a >>= (\b -> return (Leaf b))
mapTreeM f (Branch lhs rhs) = do
lhs' <- mapTreeM f lhs
rhs' <- mapTreeM f rhs
return (Branch lhs' rhs')
numberTree :: (Num a) => Tree a -> State a (Tree (a,a))
numberTree tree = mapTreeM number tree
where number v = do
cur <- getState
putState(cur+v)
return (v,cur+v)
-- An instance of a tree
testTree = (Branch
(Branch
(Leaf 7) (Branch (Leaf (-1)) (Leaf 3)))
(Branch
(Leaf (-2)) (Leaf (-20))))
runStateM :: State state a -> state -> a
runStateM (State f) st = snd (f st)
main :: IO()
main = print $ runStateM (numberTree testTree) 0

Can I propose an alternative solution to your problem? While Monads are good for many things, what you want to do can be done with a simple function that
keeps track of errors.
My function transferVal below is an example of such function.
The function transferVal traverses the
Tree from left to right while keeping the last value found. If an error occurs, the function returns the error and stops traversing the Tree.
Instead of using Maybe, it is often better to use Either <error_type> <result_type> to get a more clear error if something goes wrong. In my example, I use ([ChildDir],a) where [ChildDir] contains the
"direction" of the incriminated node and a is the erroneous value that triggered the error. The function printErrorsOrTree is an example of how you can use the output of transferVal and main contains 4 examples of which the first three are correct and the last one triggers the error that you was expecting.
module Main where
import Data.List (intercalate)
import Control.Monad (mapM_)
data Tree a = Leaf a | Branch (Tree a) (Tree a)
deriving (Show,Eq)
-- given a Branch, in which child the error is?
data ChildDir = LeftChild | RightChild
deriving Show
-- an error is the direction to get to the error from the root and the
-- value that triggered the error
type Error a = ([ChildDir],a)
-- util to append a direction to an error
appendDir :: ChildDir -> Error a -> Error a
appendDir d (ds,x) = (d:ds,x)
transferVal :: (Ord a,Num a) => Tree a -> Either (Error a) (Tree (a,a))
transferVal = fmap fst . go 0
where go :: (Ord a,Num a) => a -> Tree a -> Either (Error a) (Tree (a,a),a)
go c (Leaf x) = let newC = x + c
in if newC < 0
then Left ([],newC)
else Right (Leaf (x,newC),newC)
go c (Branch t1 t2) = case go c t1 of
Left e -> Left $ appendDir LeftChild e
Right (newT1,newC) -> case go newC t2 of
Left e -> Left $ appendDir RightChild e
Right (newT2,newC') -> Right (Branch newT1 newT2,newC')
printErrorsOrTree :: (Show a,Show b) => Either (Error a) (Tree b) -> IO ()
printErrorsOrTree (Left (ds,x)) = putStrLn $ "Error in position " ++ (intercalate " -> " $ map show ds) ++ ". Error value is " ++ show x
printErrorsOrTree (Right t) = putStrLn $ "Result: " ++ show t
main :: IO ()
main = mapM_ runExample
[(Leaf 1)
,(Branch (Leaf 1) (Leaf 2))
,(Branch (Branch (Leaf 7) (Branch (Leaf (-1)) (Leaf 3))) (Branch (Leaf (-2)) (Leaf 9)))
,(Branch (Branch (Leaf 7) (Branch (Leaf (-11)) (Leaf 3))) (Branch (Leaf (-2)) (Leaf 9)))]
where runExample orig = do
let res = transferVal orig
print orig
printErrorsOrTree res

By making your Tree datatype an instance of Traversable, you can use mapM (from Data.Traversable) to map an action over a Tree. You can also layer the StateT monad transformer atop the Either monad to provide error handling.
import Control.Monad.State
import Control.Applicative
import Control.Monad.Error
import Data.Monoid
import Data.Foldable
import Data.Traversable
import qualified Data.Traversable as T
-- our monad which carries state but allows for errors with string message
type M s = StateT s (Either String)
data Tree a = Leaf a | Branch (Tree a) (Tree a)
deriving (Show,Eq)
-- Traversable requires Functor
instance Functor Tree where
fmap f (Leaf a) = Leaf (f a)
fmap f (Branch lhs rhs) = Branch (fmap f lhs) (fmap f rhs)
-- Traversable requires Foldable
instance Foldable Tree where
foldMap f (Leaf a) = f a
foldMap f (Branch lhs rhs) = foldMap f lhs `mappend` foldMap f rhs
-- Finally, we can get to Traversable
instance Traversable Tree where
traverse f (Leaf a) = Leaf <$> f a
traverse f (Branch lhs rhs) = Branch <$> traverse f lhs <*> traverse f rhs
testTree = (Branch
(Branch
(Leaf 7) (Branch (Leaf (-1)) (Leaf 3)))
(Branch
(Leaf (-2)) (Leaf (-20))))
numberTree :: (Num a, Ord a) => Tree a -> M a (Tree (a,a))
numberTree = T.mapM number where
number v = do
cur <- get
let nxt = cur+v
-- lift the error into the StateT layer
when (nxt < 0) $ throwError "state went negative"
put nxt
return (v, nxt)
main :: IO ()
main =
case evalStateT (numberTree testTree) 0 of
Left e -> putStrLn $ "Error: " ++ e
Right t -> putStrLn $ "Success: " ++ show t

Related

How to create a tree of random values in Haskell?

I've been working on learning about the state monad. I'm working with trees, defined as follows...
data Tree a = Unary (Tree a) | Binary (Tree a) (Tree a)| Ternary (Tree a) (Tree a) (Tree a) | Leaf a
What I'm currently trying to do is make a function with type signature randomize :: Tree a -> Tree Int that returns a tree where each leaf (Leaf a) is replaced by a leaf (Leaf 0) or a (Leaf 1) with equal probability.
I previously wrote a function I called label :: Enum b => Tree a -> b -> Tree b that traverses a Tree and replaces every Leaf a with a Leaf b where b is incremented every time a leaf is visited. It is defined as follows
label:: Enum b => Tree a -> b -> Tree b
label tree b = evalState (mapSucc (\s -> (s, succ s)) tree) b where
mapSucc f (Leaf a) = Leaf <$> state f
mapSucc f (Unary t1) = Unary <$> mapSucc f t1
mapSucc f (Binary t1 t2) = Binary <$> mapSucc f t1 <*> mapSucc f t2
mapSucc f (Ternary t1 t2 t3) = Ternary <$> mapSucc f t1 <*> mapSucc f t2 <*> mapSucc f t3
These seem to be very similar problems, you are weaving the state through each, you're just producing values differently. I tried...
randomize tree = evalState ( mapRandom (randomR (0,1)) tree) newStdGen where
mapRandom f (Leaf a) = Leaf <$> state f
mapRandom f (Unary t1) = Unary <$> mapRandom f t1
mapRandom f (Binary t1 t2) = Binary <$> mapRandom f t1 <*> mapRandom f t2
mapRandom f (Ternary t1 t2 t3) = Ternary <$> mapRandom f t1 <*> mapRandom f t2 <*> mapRandom f t3
however the compiler gave me the following
state.hs:55:41: error:
• No instance for (RandomGen (IO StdGen))
arising from a use of ‘randomR’
• In the first argument of ‘mapRandom’, namely ‘(randomR (0, 1))’
In the first argument of ‘evalState’, namely
‘(mapRandom (randomR (0, 1)) tree)’
In the expression:
evalState (mapRandom (randomR (0, 1)) tree) newStdGen
I thought Int was an instance of random, so I'm not really sure what to do to get an instance of Random, and if I did manage that if my thought process is on the right path. Would my solution work if I were to get an instance of random. I guess I'm not sure if my shortcoming stems from simply not knowing how to use System.Random or if I am not understanding the type of function I need. I've spent a significant amount of time trying to make randomize work but to no avail. Any help with understanding would be greatly appreciated.
From the compiler error message, it seems the problem is caused by the fact that your random number generator comes wrapped in the IO monad, because you have used function newStdGen.
You can get an unwrapped generator by using function mkStdGen instead. This function takes a parameter of Type Int as the seed of the generator.
For example, this code compiles:
randomize :: (Random a, Num a) => Int -> Tree a -> Tree a
randomize seed tree = evalState ( mapRandom (randomR (0,1)) tree) (mkStdGen seed) where
mapRandom f (Leaf a) = Leaf <$> state f
mapRandom f (Unary t1) = Unary <$> mapRandom f t1
mapRandom f (Binary t1 t2) = Binary <$> mapRandom f t1 <*> mapRandom f t2
mapRandom f (Ternary t1 t2 t3) = Ternary <$> mapRandom f t1
<*> mapRandom f t2 <*> mapRandom f t3
and you get as a bonus the possibility to reproduce the same sequence of random numbers at will (by passing the same seed again), something that newStdGen does not provide.
Function newStdGen uses the system clock to generate the seed, hence the need to involve the IO monad.
Addendum:
How to avoid duplicating the tree traversal code
Function randomize above works. However, it is not entirely satisfactory: it involves the algorithm for tree traversal, and it decides which range of values to use, and also which type of random number generator. So it seems to fail something known in computer programming as the Single Responsibility Principle (SRP).
One might need a different range some day. Also, you can make a case that the Threefish random number generator has better statistical properties than the standard Haskell one, and wish to use its Haskell implementation.
The path of least resistance is to clone the code for randomize and replace mkStdGen by mkTFGen. But at that point, the tree traversal code gets duplicated. And there are many potential duplicates. We should find a better way.
The general problem is to produce a new version of the initial tree using a stateful mapping. Here, we have so far ignored the values in the initial tree, but this is just for the particular case of a random output tree.
Generally, the type signature of the required transformation function would have to be:
statefulTreeMap :: (a -> s -> (b,s)) -> s -> Tree a -> (Tree b, s)
where s is the type of the state. In the case of randomize, the state is just (the current state of) the random number generator.
You can easily write the code for statefulTreeMap manually, using clauses like this:
statefulTreeMap step st0 (Binary tra1 tra2) =
let (trb1, st1) = statefulTreeMap step st0 tra1
(trb2, st2) = statefulTreeMap step st1 tra2
in (Binary trb1 trb2 , st2)
But this is not really the most Haskellish way.
It turns out this is quite similar to the mapAccumL library function. And the Haskell language library makes mapAccumL available for any entity belonging to the Traversable typeclass. Note that #amalloy mentions the Traversable typeclass in one of the comments.
So we could try to make our Tree type an instance of Traversable, and then make use of function mapAccumL.
This can be done by providing the code for function traverse explicitely:
instance Traversable Tree where
traverse fn (Unary ta) = Unary <$> (traverse fn ta)
traverse fn (Binary ta tb) = Binary <$> (traverse fn ta) <*> (traverse fn tb)
traverse fn (Ternary ta tb tc) = Ternary <$> (traverse fn ta) <*> (traverse fn tb) <*> (traverse fn tc)
traverse fn (Leaf a) = Leaf <$> fn a
But this is not even necessary. Instead, one can summon the compiler heavy artillery (at least in recent enough versions), and just ask it to generate the Tree version of traverse, by enabling the DeriveTraversable language extension:
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DeriveFoldable #-}
{-# LANGUAGE DeriveTraversable #-}
import qualified Data.Tuple as T
import qualified Data.Traversable as TR
import System.Random
import qualified System.Random.TF as TF
import Control.Monad.State
data Tree a = Unary (Tree a) | Binary (Tree a) (Tree a) |
Ternary (Tree a) (Tree a) (Tree a) | Leaf a
deriving (Eq, Show, Functor, Foldable, Traversable)
Then we can have a generic version of our target statefulTreeMap function by putting some plumbing code around the mapAccumL function we've just got for free:
-- general solution for any Traversable entity:
statefulMap :: Traversable tr => (a -> s -> (b,s)) -> s -> tr a -> (tr b, s)
statefulMap step st0 tra =
let fn = \s y -> T.swap (step y s)
p = TR.mapAccumL fn st0 tra -- works in reverse if using mapAccumR
in
T.swap p
and we can immediately specialize it for Tree objects:
statefulTreeMap :: (a -> s -> (b,s)) -> s -> Tree a -> (Tree b, s)
statefulTreeMap = statefulMap
Thus we're almost done. We can now write a number of versions of randomize by supplying more plumbing code:
-- generic random tree generation, with range and generator as external parameters:
randomize2 :: (RandomGen gt, Random b, Num b) => (b,b) -> gt -> Tree a -> Tree b
randomize2 range gen tra =
let step = (\a g -> randomR range g) -- leftmost parameter ignored
in fst $ statefulTreeMap step gen tra -- drop final state of rng
-- version taking just a seed, with output range and generator type both hardwired:
randomize3 :: (Random b, Num b) => Int -> Tree a -> Tree b
randomize3 seed tra = let rng = TF.mkTFGen seed
range = (0,9)
in randomize2 range rng tra
Test code:
main = do
let seed = 4243
rng0 = TF.mkTFGen seed
tr1 = Ternary (Ternary (Leaf 1) (Leaf 2) (Leaf 3))
(Leaf (4::Integer))
(Binary (Leaf 12) (Leaf 13))
tr11 = (randomize seed tr1) :: Tree Integer
tr12 = (randomize2 (0,9) rng0 tr1) :: Tree Integer
tr13 = (randomize3 seed tr1) :: Tree Integer
putStrLn $ "tr1 = " ++ (show tr1) ++ "\n"
putStrLn $ "tr11 = " ++ (show tr11)
putStrLn $ "tr12 = " ++ (show tr12)
putStrLn $ "tr13 = " ++ (show tr13)
putStrLn $ "tr11 == tr12 = " ++ (show (tr11 == tr12))
putStrLn $ "tr11 == tr13 = " ++ (show (tr11 == tr13))
Program output:
tr1 = Ternary (Ternary (Leaf 1) (Leaf 2) (Leaf 3)) (Leaf 4) (Binary (Leaf 12) (Leaf 13))
tr11 = Ternary (Ternary (Leaf 9) (Leaf 6) (Leaf 0)) (Leaf 3) (Binary (Leaf 2) (Leaf 6))
tr12 = Ternary (Ternary (Leaf 9) (Leaf 6) (Leaf 0)) (Leaf 3) (Binary (Leaf 2) (Leaf 6))
tr13 = Ternary (Ternary (Leaf 9) (Leaf 6) (Leaf 0)) (Leaf 3) (Binary (Leaf 2) (Leaf 6))
tr11 == tr12 = True
tr11 == tr13 = True
So, in fact, we have eliminated the need for any explicit tree traversal code.
Side note:
Of course, the statefulTreeMap function can be used for tasks unrelated to pseudo-randomness. For example, we might want to give consecutive numbers to the elements of a Tree object:
enumerate :: Tree a -> Tree (a, Int)
enumerate = fst . (statefulTreeMap (\a rs -> ((a, head rs), tail rs)) [0..])
Testing under ghci:
λ>
λ> enumerate tr1
Ternary (Ternary (Leaf (1,0)) (Leaf (2,1)) (Leaf (3,2))) (Leaf (4,3)) (Binary (Leaf (12,4)) (Leaf (13,5)))
λ>
Your attempt was close. The problem is that newStdGen is an IO StdGen, but you need an StdGen. To fix that, change evalState ( mapRandom (randomR (0,1)) tree) newStdGen to evalState ( mapRandom (randomR (0,1)) tree) <$> newStdGen. Note that it'll then be randomize :: Tree a -> IO (Tree Int) rather than randomize :: Tree a -> Tree Int, but you can't avoid changing the type signature (your only other option is to make the StdGen be a parameter, which also changes it).

Sumation of tree

So for this problem I tried to take the sum of all leaves in a tree. But it's shooting an error every time. I am providing a snippet of the code I wrote.
Sample case
t1 =NODE 1 (NODE 2 (NODE 3 (LEAF 4) (LEAF 5)) (LEAF 6)) (NODE 7 (LEAF 8) (LEAF 9))
Answer should be 32.
data Tree a = LEAF a | NODE a (Tree a) (Tree a) deriving (Show, Read, Eq)
tre (LEAF a) = a
tre (NODE a (Tree b) (Tree c)) = [Tree b, Tree c]
sum [] accum = []
sum list#(x:xs) accum = if tre x == Int
then sumTree xs (accum + x)
else sumTree x accum
sumTree :: Num p => Tree p -> p
sumTree p accum= let
list = tre p
in sum list accum
32
The Haskell snipet provided is not the idiomatic Haskell way of solving the problem.
You don't need the tre function => use Pattern matching on constructors of your type
You don't have to use tre x == Int let out the magic of type inference
I've provided the following snippet of the code, load it into ghci and use :i Tree and :i sumTree to understand the types
module Main where
data Tree a = Leaf a | Node a (Tree a) (Tree a) deriving (Show)
sumTree (Leaf a) = a
sumTree (Node a l r) = a + sumTree l + sumTree r
main = do
let tree = Node 5 (Node 21 (Leaf 14) (Leaf 13)) (Leaf 29)
putStrLn $ show tree
putStrLn $ show $ sumTree tree

Fingertree head complexity

I was just reading Apfelmus' excellent introduction to Finger Trees for the second time and started to wonder about his implementation of head:
import Prelude hiding (head)
data Tree v a = Leaf v a
| Branch v (Tree v a) (Tree v a)
toList :: Tree v a -> [a]
toList (Leaf _ a) = [a]
toList (Branch _ x y) = toList x ++ toList y
head :: Tree v a -> a
head (Leaf _ a) = a
head (Branch _ x _) = head x
As implementing functions in terms of one another is a quite nice way of reusing code, it got me thinking if the following implementation would be as efficient (complexity wise) as his original:
import Prelude -- not needed, just for making it obvious
data Tree v a = Leaf v a
| Branch v (Tree v a) (Tree v a) deriving Show
toList :: Tree v a -> [a]
toList (Leaf _ a) = [a]
toList (Branch _ x y) = toList x ++ toList y
head' :: Tree v a -> a
head' = head . toList
Is lazy evaluation as efficient as the original implementation?
Yes, head and head' should have the same time complexity if handed to GHC. I would expect a small constant-factor difference in favor of head (maybe 60% confident of this -- the list fusion optimization stuff is pretty wild when it works).

Rewriting a Haskell Tree leaves function so that it gives out its computing steps as well as its result

I have the task of rewriting two Haskell functions of the Tree Datatype so that they also give out their computing steps.
The Functions are
leaves :: Tree a -> [a]
leaves Nil = []
leaves (Leaf a) = [a]
leaves (Br l r) = leaves l ++ leaves r
and
leaves'' :: Tree a -> [a]
leaves'' Nil = []
leaves'' (Leaf a) = [a]
leaves'' (Br Nil r) = leaves'' r
leaves'' (Br (Leaf a) r) = a: leaves'' r
leaves'' (Br (Br l' r') r) = leaves'' (Br l' (Br r' r))
The Datatype is
data Tree a = Leaf a |
Br (Tree a) (Tree a)|
Nil
deriving Show
I don't really even know how to begin
I don't really even know how to begin
I would start by defining what you mean by "give out their computing steps". Is your program supposed to print some output in a particular format?
The next thing you should do is decide what the new type of leaves ought to be. Not knowing the answer to the first question, one possibility is:
leaves :: Tree a -> ([ComputingStep], [a])
Or maybe you need to return the "steps" interleaved with the leaf elements?:
leaves :: Tree a -> [Either ComputingStep a]
From here, start with your base cases and go from there. You might like to look at a function like splitAt from Data.List for inspiration (an example of a recursive function that returns a tuple).
From comments I guessed you only need information how many function calls did you make. You may just sum them in pretty simple way:
leaves :: Tree a -> (Int, [a])
leaves''' Nil = (1, [])
leaves''' (Leaf a) = (1, [a])
leaves''' (Br l r) = let (n1, resl) = leaves''' l
(n2, resr) = leaves''' r
in (n1 + n2 + 1, resl ++ resr)
(and second variant in similar way)

Haskell - Create a fold function for tree type

I have this simple data Tree :
data Tree = Leaf Int | Node [Tree]
And I have to devellop a fold function for this type :
foldTree :: (Int -> a) -> ([a] -> a) -> Tree -> a
for example :
foldTree (+1) sum (Node[ (Leaf 2), (Leaf 3)])
will return (2+1)+(3+1) = 7
For leafs, I have :
foldTree f g (Leaf n) = (f n)
But I have no ideas for develop the nodes's case.
I'm french, also sorry for the mistakes.
It sometimes helps to look at what is available in scope and their types. Here's a solution:
foldTree f g (Leaf n) = (f n)
foldTree f g (Node subtrees) =
let as = map (foldTree f g) subtrees -- as :: [a]
in g as

Resources