-
Notifications
You must be signed in to change notification settings - Fork 0
/
Nondeterministic.hs
109 lines (85 loc) · 3.25 KB
/
Nondeterministic.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}
-- for "instance MonadWriter w (NondetWriter w)"
module Nondeterministic
(
MonadNondet (..)
, NondetWriter
, drawTreeBy
) where
import Data.Monoid
-- import Control.Monad
import Control.Applicative
import Control.Monad.Reader
import Control.Monad.Writer.Class
class (Monad m) => MonadNondet m where
chooseNondet :: [m a] -> m a
data NondetWriter w a =
Leaf w a
| Node w [NondetWriter w a]
deriving Show
instance Functor (NondetWriter w) where
fmap f (Leaf w a) = Leaf w (f a)
fmap f (Node w trees) = Node w (map (fmap f) trees)
instance (Monoid w) => Applicative (NondetWriter w) where
pure a = Leaf mempty a
(<*>) = undefined
instance (Monoid w) => Monad (NondetWriter w) where
return = pure
(Leaf w a) >>= f = case f a of
Leaf v b -> Leaf (w <> v) b
Node v b -> Node (w <> v) b
(Node w trees) >>= f = Node w $ map (>>= f) trees
instance (Monoid w) => MonadNondet (NondetWriter w) where
chooseNondet = Node mempty
instance (Monoid w) => MonadWriter w (NondetWriter w) where
writer (a, w) = Leaf w a
listen = go mempty where
go v (Leaf w a) = Leaf w (a, v <> w)
go v (Node w trees) = Node w $ map (go (v <> w)) trees
-- Warning: this implementation of pass might be correct only for some good f
pass (Leaf w (a, f)) = Leaf (f w) a
pass (Node w trees) = Node w $ map pass trees
depth :: NondetWriter w a -> Int
depth (Leaf _ _) = 0
depth (Node _ trees) = 1 + maximum (0 : map depth trees)
drawTreeBy ::
(s -> w -> (s, [String])) -> s -> (a -> String) -> NondetWriter w a -> String
drawTreeBy showw showwAux showa t =
unlines . map (softTab (2 * depth t + 3)) . flip runReader showwAux . draw $ t
where
softTab :: Int -> (String, String) -> String
softTab _ (strl, "") = strl
softTab tabstop (strl, strr) = (take tabstop $ strl ++ repeat ' ') ++ strr
showw' w cont = do
aux <- ask
let (aux', strs) = showw aux w
rest <- local (const aux') cont
return $ zip ("." : repeat "|") strs ++ rest
-- draw :: NondetWriter w a -> [(String, String)]
draw (Leaf w a) = showw' w $ return [(showa a, "")]
draw (Node w trees) = showw' w $ drawSubTrees trees
drawSubTrees [] = return [("$", "")]
drawSubTrees [t] = shift "`-" " " <$> draw t
drawSubTrees (t : ts) = (++) <$>
(shift "+-" "| " <$> draw t) <*>
(drawSubTrees ts)
shift first other =
zipWith (\ sh (l, r) -> (sh ++ l, r)) (first : repeat other)
-- (cf. Data.Tree)
{-
drawTreeBy :: (w -> [String]) -> (a -> String) -> NondetWriter w a -> String
drawTreeBy showw showa t = unlines . map (softTab (2 * depth t + 3)) . draw $ t
where
softTab :: Int -> (String, String) -> String
softTab _ (strl, "") = strl
softTab tabstop (strl, strr) = (take tabstop $ strl ++ repeat ' ') ++ strr
showw' = zip ("." : repeat "|") . showw
-- draw :: NondetWriter w a -> [(String, String)]
draw (Leaf w a) = showw' w ++ [(showa a, "")]
draw (Node w trees) = showw' w ++ drawSubTrees trees
drawSubTrees [] = [("$", "")]
drawSubTrees [t] = shift "`-" " " (draw t)
drawSubTrees (t : ts) = shift "+-" "| " (draw t) ++ drawSubTrees ts
shift first other =
zipWith (\ sh (l, r) -> (sh ++ l, r)) (first : repeat other)
-}