| 
									
										
										
										
											2008-05-03 05:44:02 -04:00
										 |  |  | ! Copyright (C) 2008 Slava Pestov | 
					
						
							|  |  |  | ! See http://factorcode.org/license.txt for BSD license. | 
					
						
							|  |  |  | USING: arrays kernel sequences sequences.deep splitting | 
					
						
							| 
									
										
										
										
											2008-06-03 04:27:25 -04:00
										 |  |  | accessors fry locals combinators namespaces lists lists.lazy | 
					
						
							| 
									
										
										
										
											2008-05-03 05:44:02 -04:00
										 |  |  | shuffle ;
 | 
					
						
							|  |  |  | IN: monads | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ! Functors | 
					
						
							| 
									
										
										
										
											2009-03-16 21:11:36 -04:00
										 |  |  | GENERIC# fmap 1 ( functor quot -- functor' )
 | 
					
						
							| 
									
										
										
										
											2009-06-27 14:31:22 -04:00
										 |  |  | GENERIC# <$ 1 ( functor quot -- functor' )
 | 
					
						
							| 
									
										
										
										
											2009-07-27 22:44:18 -04:00
										 |  |  | GENERIC# $> 1 ( functor quot -- functor' )
 | 
					
						
							| 
									
										
										
										
											2008-05-03 05:44:02 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | ! Monads | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ! Mixin type for monad singleton classes, used for return/fail only | 
					
						
							|  |  |  | MIXIN: monad | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GENERIC: monad-of ( mvalue -- singleton )
 | 
					
						
							| 
									
										
										
										
											2008-06-09 03:14:14 -04:00
										 |  |  | GENERIC: return ( value singleton -- mvalue )
 | 
					
						
							| 
									
										
										
										
											2008-05-03 05:44:02 -04:00
										 |  |  | GENERIC: fail ( value singleton -- mvalue )
 | 
					
						
							|  |  |  | GENERIC: >>= ( mvalue -- quot )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: monad return monad-of return ;
 | 
					
						
							|  |  |  | M: monad fail   monad-of fail   ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-16 21:11:36 -04:00
										 |  |  | : bind ( mvalue quot -- mvalue' ) swap >>= call( quot -- mvalue ) ;
 | 
					
						
							| 
									
										
										
										
											2009-05-24 10:36:24 -04:00
										 |  |  | : bind* ( mvalue quot -- mvalue' ) '[ drop @ ] bind ;
 | 
					
						
							| 
									
										
										
										
											2008-09-10 23:11:40 -04:00
										 |  |  | : >>   ( mvalue k -- mvalue' ) '[ drop _ ] bind ;
 | 
					
						
							| 
									
										
										
										
											2008-05-03 05:44:02 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | :: lift-m2 ( m1 m2 f monad -- m3 )
 | 
					
						
							|  |  |  |     m1 [| x1 | m2 [| x2 | x1 x2 f monad return ] bind ] bind ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :: apply ( mvalue mquot monad -- result )
 | 
					
						
							|  |  |  |     mvalue [| value | | 
					
						
							|  |  |  |         mquot [| quot | | 
					
						
							| 
									
										
										
										
											2009-03-16 21:11:36 -04:00
										 |  |  |             value quot call( value -- mvalue ) monad return
 | 
					
						
							| 
									
										
										
										
											2008-05-03 05:44:02 -04:00
										 |  |  |         ] bind | 
					
						
							|  |  |  |     ] bind ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-10 23:11:40 -04:00
										 |  |  | M: monad fmap over '[ @ _ return ] bind ;
 | 
					
						
							| 
									
										
										
										
											2008-05-03 05:44:02 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | ! 'do' notation | 
					
						
							| 
									
										
										
										
											2009-03-16 21:11:36 -04:00
										 |  |  | : do ( quots -- result ) unclip [ call( -- mvalue ) ] curry dip [ bind ] each ;
 | 
					
						
							| 
									
										
										
										
											2008-05-03 05:44:02 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | ! Identity | 
					
						
							|  |  |  | SINGLETON: identity-monad | 
					
						
							|  |  |  | INSTANCE:  identity-monad monad | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TUPLE: identity value ;
 | 
					
						
							|  |  |  | INSTANCE: identity monad | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: identity monad-of drop identity-monad ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: identity-monad return drop identity boa ;
 | 
					
						
							|  |  |  | M: identity-monad fail   "Fail" throw ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-16 21:11:36 -04:00
										 |  |  | M: identity >>= value>> '[ _ swap call( x -- y ) ] ;
 | 
					
						
							| 
									
										
										
										
											2008-05-03 05:44:02 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : run-identity ( identity -- value ) value>> ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ! Maybe | 
					
						
							|  |  |  | SINGLETON: maybe-monad | 
					
						
							|  |  |  | INSTANCE:  maybe-monad monad | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SINGLETON: nothing | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TUPLE: just value ;
 | 
					
						
							| 
									
										
										
										
											2008-06-09 03:14:14 -04:00
										 |  |  | : just ( value -- just ) \ just boa ;
 | 
					
						
							| 
									
										
										
										
											2008-05-03 05:44:02 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | UNION: maybe just nothing ;
 | 
					
						
							|  |  |  | INSTANCE: maybe monad | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: maybe monad-of drop maybe-monad ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: maybe-monad return drop just ;
 | 
					
						
							|  |  |  | M: maybe-monad fail   2drop nothing ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-10 23:11:40 -04:00
										 |  |  | M: nothing >>= '[ drop _ ] ;
 | 
					
						
							| 
									
										
										
										
											2009-03-16 21:11:36 -04:00
										 |  |  | M: just    >>= value>> '[ _ swap call( x -- y ) ] ;
 | 
					
						
							| 
									
										
										
										
											2008-05-03 05:44:02 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : if-maybe ( maybe just-quot nothing-quot -- )
 | 
					
						
							|  |  |  |     pick nothing? [ 2nip call ] [ drop [ value>> ] dip call ] if ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ! Either | 
					
						
							|  |  |  | SINGLETON: either-monad | 
					
						
							|  |  |  | INSTANCE:  either-monad monad | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TUPLE: left value ;
 | 
					
						
							| 
									
										
										
										
											2008-06-09 03:14:14 -04:00
										 |  |  | : left ( value -- left ) \ left boa ;
 | 
					
						
							| 
									
										
										
										
											2008-05-03 05:44:02 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | TUPLE: right value ;
 | 
					
						
							| 
									
										
										
										
											2008-06-09 03:14:14 -04:00
										 |  |  | : right ( value -- right ) \ right boa ;
 | 
					
						
							| 
									
										
										
										
											2008-05-03 05:44:02 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | UNION: either left right ;
 | 
					
						
							|  |  |  | INSTANCE: either monad | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: either monad-of drop either-monad ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: either-monad return  drop right ;
 | 
					
						
							|  |  |  | M: either-monad fail    drop left ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-10 23:11:40 -04:00
										 |  |  | M: left  >>= '[ drop _ ] ;
 | 
					
						
							| 
									
										
										
										
											2009-03-16 21:11:36 -04:00
										 |  |  | M: right >>= value>> '[ _ swap call( x -- y ) ] ;
 | 
					
						
							| 
									
										
										
										
											2008-05-03 05:44:02 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : if-either ( value left-quot right-quot -- )
 | 
					
						
							|  |  |  |     [ [ value>> ] [ left? ] bi ] 2dip if ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ! Arrays | 
					
						
							|  |  |  | SINGLETON: array-monad | 
					
						
							|  |  |  | INSTANCE:  array-monad monad | 
					
						
							|  |  |  | INSTANCE:  array monad | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: array-monad return  drop 1array ;
 | 
					
						
							|  |  |  | M: array-monad fail   2drop { } ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: array monad-of drop array-monad ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-10 23:11:40 -04:00
										 |  |  | M: array >>= '[ _ swap map concat ] ;
 | 
					
						
							| 
									
										
										
										
											2008-05-03 05:44:02 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | ! List | 
					
						
							|  |  |  | SINGLETON: list-monad | 
					
						
							|  |  |  | INSTANCE:  list-monad monad | 
					
						
							|  |  |  | INSTANCE:  list monad | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: list-monad return drop 1list ;
 | 
					
						
							|  |  |  | M: list-monad fail   2drop nil ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: list monad-of drop list-monad ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-10 23:11:40 -04:00
										 |  |  | M: list >>= '[ _ swap lazy-map lconcat ] ;
 | 
					
						
							| 
									
										
										
										
											2008-05-03 05:44:02 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | ! State | 
					
						
							|  |  |  | SINGLETON: state-monad | 
					
						
							|  |  |  | INSTANCE:  state-monad monad | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TUPLE: state quot ;
 | 
					
						
							| 
									
										
										
										
											2008-06-09 03:14:14 -04:00
										 |  |  | : state ( quot -- state ) \ state boa ;
 | 
					
						
							| 
									
										
										
										
											2008-05-03 05:44:02 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | INSTANCE: state monad | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: state monad-of drop state-monad ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-10 23:11:40 -04:00
										 |  |  | M: state-monad return drop '[ _ 2array ] state ;
 | 
					
						
							| 
									
										
										
										
											2008-05-03 05:44:02 -04:00
										 |  |  | M: state-monad fail   "Fail" throw ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-16 21:11:36 -04:00
										 |  |  | : mcall ( x state -- y ) quot>> call( x -- y ) ;
 | 
					
						
							| 
									
										
										
										
											2008-05-03 05:44:02 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-10 23:11:40 -04:00
										 |  |  | M: state >>= '[ _ swap '[ _ mcall first2 @ mcall ] state ] ;
 | 
					
						
							| 
									
										
										
										
											2008-05-03 05:44:02 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : get-st ( -- state ) [ dup 2array ] state ;
 | 
					
						
							| 
									
										
										
										
											2008-09-10 23:11:40 -04:00
										 |  |  | : put-st ( value -- state ) '[ drop _ f 2array ] state ;
 | 
					
						
							| 
									
										
										
										
											2008-05-03 05:44:02 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-16 21:11:36 -04:00
										 |  |  | : run-st ( state initial -- value ) swap mcall second ;
 | 
					
						
							| 
									
										
										
										
											2008-05-03 05:44:02 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-06-09 03:14:14 -04:00
										 |  |  | : return-st ( value -- mvalue ) state-monad return ;
 | 
					
						
							| 
									
										
										
										
											2008-05-03 05:44:02 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | ! Reader | 
					
						
							|  |  |  | SINGLETON: reader-monad | 
					
						
							|  |  |  | INSTANCE:  reader-monad monad | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TUPLE: reader quot ;
 | 
					
						
							| 
									
										
										
										
											2008-06-09 03:14:14 -04:00
										 |  |  | : reader ( quot -- reader ) \ reader boa ;
 | 
					
						
							| 
									
										
										
										
											2008-05-03 05:44:02 -04:00
										 |  |  | INSTANCE: reader monad | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: reader monad-of drop reader-monad ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-10 23:11:40 -04:00
										 |  |  | M: reader-monad return drop '[ drop _ ] reader ;
 | 
					
						
							| 
									
										
										
										
											2008-05-03 05:44:02 -04:00
										 |  |  | M: reader-monad fail   "Fail" throw ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-10 23:11:40 -04:00
										 |  |  | M: reader >>= '[ _ swap '[ dup _ mcall @ mcall ] reader ] ;
 | 
					
						
							| 
									
										
										
										
											2008-05-03 05:44:02 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-16 21:11:36 -04:00
										 |  |  | : run-reader ( reader env -- value ) swap quot>> call( env -- value ) ;
 | 
					
						
							| 
									
										
										
										
											2008-05-03 05:44:02 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : ask ( -- reader ) [ ] reader ;
 | 
					
						
							| 
									
										
										
										
											2008-09-10 23:11:40 -04:00
										 |  |  | : local ( reader quot -- reader' ) swap '[ @ _ mcall ] reader ;
 | 
					
						
							| 
									
										
										
										
											2008-05-03 05:44:02 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | ! Writer | 
					
						
							|  |  |  | SINGLETON: writer-monad | 
					
						
							|  |  |  | INSTANCE:  writer-monad monad | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TUPLE: writer value log ;
 | 
					
						
							| 
									
										
										
										
											2008-06-09 03:14:14 -04:00
										 |  |  | : writer ( value log -- writer ) \ writer boa ;
 | 
					
						
							| 
									
										
										
										
											2008-05-03 05:44:02 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: writer monad-of drop writer-monad ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: writer-monad return drop { } writer ;
 | 
					
						
							|  |  |  | M: writer-monad fail   "Fail" throw ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : run-writer ( writer -- value log ) [ value>> ] [ log>> ] bi ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-10 23:11:40 -04:00
										 |  |  | M: writer >>= '[ [ _ run-writer ] dip '[ @ run-writer ] dip append writer ] ;
 | 
					
						
							| 
									
										
										
										
											2008-05-03 05:44:02 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-16 21:11:36 -04:00
										 |  |  | : pass ( writer -- writer' ) run-writer [ first2 ] dip swap call( x -- y ) writer ;
 | 
					
						
							| 
									
										
										
										
											2008-05-03 05:44:02 -04:00
										 |  |  | : listen ( writer -- writer' ) run-writer [ 2array ] keep writer ;
 | 
					
						
							|  |  |  | : tell ( seq -- writer ) f swap writer ;
 |