3.3 Instances
3.3.1 Box
(require algebraic/data/box) | package: algebraic |
instance
value
value
value
> (with-instance box-applicative (<*> (pure add1) (pure 2))) '#&3
> (with-instance box-applicative (liftA2 + (pure 4) (pure 5))) '#&9
instance
value
> (with-instance box-functor (fmap (>> :: '!) #&?)) '#&(! . ?)
instance
value
3.3.2 Event
(require algebraic/data/event) | package: algebraic |
instance
value
value
> (with-instance event-applicative (sync (pure 1 2 3)))
1
2
3
> (with-instance event-applicative (sync (liftA2 list (pure 1 2) (pure 3 4)))) '(1 2 3 4)
instance
value
> (with-instance event-functor (sync (fmap (λ _ (id 1 2 3)) always-evt)))
1
2
3
instance
value
value
> (with-instance event-monad (sync (>>= (return 1 2 3) (.. return +)))) 6
3.3.3 List
(require algebraic/data/list) | package: algebraic |
instance
value
value
value
value
*> : procedure?
> (with-instance list-applicative (pure 1)) '(1)
> (with-instance list-applicative (<*> (<*> (pure (>>* ::)) '(1)) '(2))) '((1 . 2))
> (with-instance list-applicative (liftA2 :: '(?) '(!))) '((? . !))
> (with-instance list-applicative (*> '(1) '(2))) '(2)
instance
value
> (with-instance list-functor (fmap add1 '(1 2 3 4))) '(2 3 4 5)
instance
value
value
value
value
> (with-instance list-monad (>>= (return 2) (.. return add1))) '(3)
> (with-instance list-monad (>>M (return 1) (return 2))) '(2)
> (with-instance list-monad (fail '!?)) '()
> (with-instance list-monad (join '((1) (2)))) '(1 2)
instance
value
mempty : null?
value
mconcat : procedure?
> (with-instance list-monoid (mconcat '(1 2) '(3 4) mempty)) '(1 2 3 4)
instance
value
<> : procedure?
value
> (with-instance list-semigroup (<> '(1 2) '(3 4))) '(1 2 3 4)
> (with-instance list-semigroup (stimes 3 '(! ?))) '(! ? ! ? ! ?)
3.3.4 Maybe
(require algebraic/data/maybe) | package: algebraic |
The Maybe sum, and associated operations.
The Maybe sum is also a monad. It is a simple kind of error monad, where all errors are represented by Nothing. A richer error monad can be built using the Either type.
product
product
instance
value
value
value
value
*> : procedure?
> (with-instance maybe-applicative (pure 1)) (Just 1)
> (with-instance maybe-applicative (<*> (pure add1) (pure 2))) (Just 3)
> (with-instance maybe-applicative (<*> (pure add1) Nothing)) Nothing
> (with-instance maybe-applicative (<*> Nothing (pure 2))) Nothing
> (with-instance maybe-applicative (liftA2 + (pure 1) (pure 2))) (Just 3)
> (with-instance maybe-applicative (liftA2 + Nothing (pure 2))) Nothing
> (with-instance maybe-applicative (liftA2 + (pure 1) Nothing)) Nothing
> (with-instance maybe-applicative (*> (pure 1) (pure 2))) (Just 2)
> (with-instance maybe-applicative (*> Nothing (pure 2))) Nothing
> (with-instance maybe-applicative (*> (pure 1) Nothing)) Nothing
instance
value
> (with-instance maybe-functor (fmap add1 (Just 2))) (Just 3)
> (with-instance maybe-functor (fmap add1 Nothing)) Nothing
instance
value
value
value
> (with-instance maybe-monad (>>= (Just 2) (.. return add1))) (Just 3)
> (with-instance maybe-monad (>>= Nothing (.. Just add1))) Nothing
> (with-instance maybe-monad (>>M (Just 1) (Just 2))) (Just 2)
> (with-instance maybe-monad (>>M Nothing (Just 2))) Nothing
> (with-instance maybe-monad (fail '!!)) Nothing
3.3.5 Truthy
(require algebraic/data/truthy) | package: algebraic |
The Truthy sum, and associated operations.
product
Functions that return #f to indicate failure can be chained together with and and or.
> (define Δ (make-hasheq))
> (or (hash-ref Δ 'A #f) (and (hash-set! Δ 'A (random 100)) (hash-ref Δ 'A))) 40
> Δ '#hasheq((A . 40))
But #f does not always indicate failure.
> (hash-set! Δ 'B #f)
> (or (hash-ref Δ 'B #f) (and (hash-set! Δ 'B (random 100)) (hash-ref Δ 'B))) 28
> Δ '#hasheq((A . 40) (B . 28))
The Truthy monad uses the Fail product as a failure indicator distinct from #f.
Truthy is like the Maybe sum if Just were implicitly applied to all non-#f values.
> (id (hash-ref Δ 'B (const Fail)) (hash-ref Δ 'C (const Fail)))
28
Fail
Truthy is a lazy monad. With do~-notation, several Truthy expressions can be evaluated in sequence. If an expression evaluates to Fail, the sequence short circuits.
> (hash-set! Δ 'C #f)
> (with-instance truthy-monad ((do~ (λ () ((function [Fail #t] [_ Fail]) ((do~ (λ () (hash-ref Δ 'C (const Fail))))))) (do~ (λ () (hash-set! Δ 'C (random 100))) (λ () (hash-ref Δ 'C)))))) Fail
> Δ '#hasheq((A . 40) (B . 28) (C . #f))
> (with-instance truthy-monad ((do~ (λ () ((function [Fail #t] [_ Fail]) ((do~ (λ () (hash-ref Δ 'D (const Fail))))))) (do~ (λ () (hash-set! Δ 'D (random 100))) (λ () (hash-ref Δ 'D)))))) 27
> Δ '#hasheq((A . 40) (B . 28) (C . #f) (D . 27))
As a convenience, truthy-and, truthy-not, and truthy-or reduce the boilerplate.
> (with-instance truthy-monad (truthy-or (truthy-and (hash-ref Δ 'C (const Fail))) (truthy-and (hash-set! Δ 'C (random 100)) (hash-ref Δ 'C)))) #f
> Δ '#hasheq((A . 40) (B . 28) (C . #f) (D . 27))
> (with-instance truthy-monad (truthy-or (truthy-and (hash-ref Δ 'D (const Fail))) (truthy-and (hash-set! Δ 'D (random 100)) (hash-ref Δ 'D)))) 27
> Δ '#hasheq((A . 40) (B . 28) (C . #f) (D . 27))
3.3.6 Values
(require algebraic/data/values) | package: algebraic |
instance
value
value
> (with-instance values-applicative (pure 1 2 3))
1
2
3
> (with-instance values-applicative (liftA2 list (λ () (pure 1 2)) (λ () (pure 3 4)))) '(1 2 3 4)
instance
value
> (with-instance values-functor (fmap list (λ () (id 1 2 3)))) '(1 2 3)
instance
value
value
value
> (with-instance values-monad (>>= (λ () (return 1 2 3)) +)) 6
> (with-instance values-monad (>>M (λ () 1) (λ () 2))) 2