This repository has been archived by the owner on Feb 2, 2021. It is now read-only.
/
Eq.purs
90 lines (78 loc) · 2.45 KB
/
Eq.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
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
module Data.Incremental.Eq
( Atomic(..)
, replace
, map
, lift2
, apply
, mapAtomic
) where
import Prelude hiding (map, apply)
import Prelude as Prelude
import Data.Incremental (class Diff, class Patch, Change, Jet, fromChange, toChange)
import Data.Maybe (Maybe(..), fromMaybe)
import Data.Maybe.Last (Last(..))
import Data.Newtype (class Newtype, unwrap, wrap)
-- | A change structure for any type with equality.
newtype Atomic a = Atomic a
derive instance eqAtomic :: Eq a => Eq (Atomic a)
derive instance ordAtomic :: Ord a => Ord (Atomic a)
derive instance newtypeAtomic :: Newtype (Atomic a) _
instance showAtomic :: Show a => Show (Atomic a) where
show (Atomic a) = "(Atomic " <> show a <> ")"
instance patchAtomic :: Patch (Atomic a) (Last a) where
patch x (Last Nothing) = x
patch _ (Last (Just y)) = Atomic y
instance diffAtomic :: Eq a => Diff (Atomic a) (Last a) where
diff (Atomic x) (Atomic y)
| x == y = Last Nothing
| otherwise = Last (Just y)
-- | Change by replacing the current value.
replace :: forall a. a -> Change (Atomic a)
replace a = toChange (Last (Just a))
-- | Change an `Atomic` value using a regular function.
-- |
-- | This alias for `map` will be removed in a future version.
mapAtomic
:: forall a b
. (a -> b)
-> Jet (Atomic a)
-> Jet (Atomic b)
mapAtomic f { position, velocity } =
{ position: wrap (f (unwrap position))
, velocity: toChange (Prelude.map f (fromChange velocity))
}
-- | Change an `Atomic` value using a regular function.
map
:: forall a b
. (a -> b)
-> Jet (Atomic a)
-> Jet (Atomic b)
map = mapAtomic
-- | Combine two `Atomic` values using a regular function.
-- |
-- | _Note_: The result will change (entirely) if either argument
-- | changes. If changes should be independent, consider using a `Tuple`
-- | instead.
lift2
:: forall a b c
. (a -> b -> c)
-> Jet (Atomic a)
-> Jet (Atomic b)
-> Jet (Atomic c)
lift2 f a b =
{ position: wrap (f (unwrap a.position) (unwrap b.position))
, velocity: toChange (combine f (fromChange a.velocity) (fromChange b.velocity))
}
where
combine _ (Last Nothing) (Last Nothing) =
Last Nothing
combine g (Last a') (Last b') =
Last (Just (g (fromMaybe (unwrap a.position) a')
(fromMaybe (unwrap b.position) b')))
-- | Combine two `Atomic` values in an applicative style.
apply
:: forall a b
. Jet (Atomic (a -> b))
-> Jet (Atomic a)
-> Jet (Atomic b)
apply = lift2 ($)