1 ! Copyright (C) 2008 Slava Pestov
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: arrays kernel sequences sequences.deep splitting
4 accessors fry locals combinators namespaces lists lists.lazy
9 GENERIC# fmap 1 ( functor quot -- functor' )
10 GENERIC# <$ 1 ( functor quot -- functor' )
14 ! Mixin type for monad singleton classes, used for return/fail only
17 GENERIC: monad-of ( mvalue -- singleton )
18 GENERIC: return ( value singleton -- mvalue )
19 GENERIC: fail ( value singleton -- mvalue )
20 GENERIC: >>= ( mvalue -- quot )
22 M: monad return monad-of return ;
23 M: monad fail monad-of fail ;
25 : bind ( mvalue quot -- mvalue' ) swap >>= call( quot -- mvalue ) ;
26 : bind* ( mvalue quot -- mvalue' ) '[ drop @ ] bind ;
27 : >> ( mvalue k -- mvalue' ) '[ drop _ ] bind ;
29 :: lift-m2 ( m1 m2 f monad -- m3 )
30 m1 [| x1 | m2 [| x2 | x1 x2 f monad return ] bind ] bind ;
32 :: apply ( mvalue mquot monad -- result )
35 value quot call( value -- mvalue ) monad return
39 M: monad fmap over '[ @ _ return ] bind ;
42 : do ( quots -- result ) unclip [ call( -- mvalue ) ] curry dip [ bind ] each ;
45 SINGLETON: identity-monad
46 INSTANCE: identity-monad monad
48 TUPLE: identity value ;
49 INSTANCE: identity monad
51 M: identity monad-of drop identity-monad ;
53 M: identity-monad return drop identity boa ;
54 M: identity-monad fail "Fail" throw ;
56 M: identity >>= value>> '[ _ swap call( x -- y ) ] ;
58 : run-identity ( identity -- value ) value>> ;
61 SINGLETON: maybe-monad
62 INSTANCE: maybe-monad monad
67 : just ( value -- just ) \ just boa ;
69 UNION: maybe just nothing ;
72 M: maybe monad-of drop maybe-monad ;
74 M: maybe-monad return drop just ;
75 M: maybe-monad fail 2drop nothing ;
77 M: nothing >>= '[ drop _ ] ;
78 M: just >>= value>> '[ _ swap call( x -- y ) ] ;
80 : if-maybe ( maybe just-quot nothing-quot -- )
81 pick nothing? [ 2nip call ] [ drop [ value>> ] dip call ] if ; inline
84 SINGLETON: either-monad
85 INSTANCE: either-monad monad
88 : left ( value -- left ) \ left boa ;
91 : right ( value -- right ) \ right boa ;
93 UNION: either left right ;
94 INSTANCE: either monad
96 M: either monad-of drop either-monad ;
98 M: either-monad return drop right ;
99 M: either-monad fail drop left ;
101 M: left >>= '[ drop _ ] ;
102 M: right >>= value>> '[ _ swap call( x -- y ) ] ;
104 : if-either ( value left-quot right-quot -- )
105 [ [ value>> ] [ left? ] bi ] 2dip if ; inline
108 SINGLETON: array-monad
109 INSTANCE: array-monad monad
110 INSTANCE: array monad
112 M: array-monad return drop 1array ;
113 M: array-monad fail 2drop { } ;
115 M: array monad-of drop array-monad ;
117 M: array >>= '[ _ swap map concat ] ;
120 SINGLETON: list-monad
121 INSTANCE: list-monad monad
124 M: list-monad return drop 1list ;
125 M: list-monad fail 2drop nil ;
127 M: list monad-of drop list-monad ;
129 M: list >>= '[ _ swap lazy-map lconcat ] ;
132 SINGLETON: state-monad
133 INSTANCE: state-monad monad
136 : state ( quot -- state ) \ state boa ;
138 INSTANCE: state monad
140 M: state monad-of drop state-monad ;
142 M: state-monad return drop '[ _ 2array ] state ;
143 M: state-monad fail "Fail" throw ;
145 : mcall ( x state -- y ) quot>> call( x -- y ) ;
147 M: state >>= '[ _ swap '[ _ mcall first2 @ mcall ] state ] ;
149 : get-st ( -- state ) [ dup 2array ] state ;
150 : put-st ( value -- state ) '[ drop _ f 2array ] state ;
152 : run-st ( state initial -- value ) swap mcall second ;
154 : return-st ( value -- mvalue ) state-monad return ;
157 SINGLETON: reader-monad
158 INSTANCE: reader-monad monad
161 : reader ( quot -- reader ) \ reader boa ;
162 INSTANCE: reader monad
164 M: reader monad-of drop reader-monad ;
166 M: reader-monad return drop '[ drop _ ] reader ;
167 M: reader-monad fail "Fail" throw ;
169 M: reader >>= '[ _ swap '[ dup _ mcall @ mcall ] reader ] ;
171 : run-reader ( reader env -- value ) swap quot>> call( env -- value ) ;
173 : ask ( -- reader ) [ ] reader ;
174 : local ( reader quot -- reader' ) swap '[ @ _ mcall ] reader ;
177 SINGLETON: writer-monad
178 INSTANCE: writer-monad monad
180 TUPLE: writer value log ;
181 : writer ( value log -- writer ) \ writer boa ;
183 M: writer monad-of drop writer-monad ;
185 M: writer-monad return drop { } writer ;
186 M: writer-monad fail "Fail" throw ;
188 : run-writer ( writer -- value log ) [ value>> ] [ log>> ] bi ;
190 M: writer >>= '[ [ _ run-writer ] dip '[ @ run-writer ] dip append writer ] ;
192 : pass ( writer -- writer' ) run-writer [ first2 ] dip swap call( x -- y ) writer ;
193 : listen ( writer -- writer' ) run-writer [ 2array ] keep writer ;
194 : tell ( seq -- writer ) f swap writer ;