/
Utils.purs
58 lines (54 loc) · 1.82 KB
/
Utils.purs
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
module Redox.Utils where
import Prelude
import Control.Comonad.Cofree (Cofree, head, tail, (:<))
import Redox.Store as O
import Redox.Store (Store)
-- | A version of `hoistCofree`, where `nat` does not need to come from natural
-- | transformation.
-- | This corresponds to
-- | [applyMiddleware](https://github.com/reactjs/redux/blob/master/src/applyMiddleware.js)
-- | in the [redux](https://github.com/reactjs/redux) library.
-- | You can use this function to add effects to your interpreter, like
-- | logging, optimistic updates, undo/redo stack, delayed actions...
-- | For example a simple logger:
-- | ```purescript
-- | addLogger
-- | :: forall state f
-- | . (Functor f)
-- | => Cofree f state
-- | -> Cofree f state
-- | addLogger interp = hoistCofree' nat interp
-- | where
-- | nat :: f (Cofree f state) -> f (Cofree f state)
-- | nat fa = g <$> fa
-- |
-- | g :: Cofree f state -> Cofree f state
-- | g cof = unsafePerformEff do
-- | -- Control.Comonad.Cofree.head
-- | log $ unsafeCoerce (head cof)
-- | pure cof
-- | ```purescript
hoistCofree'
:: forall f state
. (Functor f)
=> (f (Cofree f state) -> f (Cofree f state))
-> Cofree f state
-> Cofree f state
hoistCofree' nat cf = head cf :< nat (hoistCofree' nat <$> tail cf)
-- | Make interpreter which updates the store on every step of computation.
-- | You have to supply the store and interperter of type `Cofree f state`.
-- | Check out tests how you can use it.
mkIncInterp
:: forall state f
. (Functor f)
=> Store state
-> Cofree f state
-> Cofree f state
mkIncInterp store interp = hoistCofree' nat interp
where
nat
:: f (Cofree f state)
-> f (Cofree f state)
nat fa = g <$> fa
g :: Cofree f state -> Cofree f state
g cof = O.performWriteRedoxEff $ cof <$ O.setState store (head cof)