forked from purescript/purescript-lazy
/
Lazy.purs
146 lines (110 loc) · 4.61 KB
/
Lazy.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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
module Data.Lazy where
import Prelude
import Control.Comonad (class Comonad)
import Control.Extend (class Extend)
import Control.Lazy as CL
import Data.Eq (class Eq1)
import Data.Foldable (class Foldable, foldMap, foldl, foldr)
import Data.FoldableWithIndex (class FoldableWithIndex)
import Data.Functor.Invariant (class Invariant, imapF)
import Data.FunctorWithIndex (class FunctorWithIndex)
import Data.HeytingAlgebra (implies, ff, tt)
import Data.Ord (class Ord1)
import Data.Semigroup.Foldable (class Foldable1)
import Data.Semigroup.Traversable (class Traversable1)
import Data.Traversable (class Traversable, traverse)
import Data.TraversableWithIndex (class TraversableWithIndex)
-- | `Lazy a` represents lazily-computed values of type `a`.
-- |
-- | A lazy value is computed at most once - the result is saved
-- | after the first computation, and subsequent attempts to read
-- | the value simply return the saved value.
-- |
-- | `Lazy` values can be created with `defer`, or by using the provided
-- | type class instances.
-- |
-- | `Lazy` values can be evaluated by using the `force` function.
-- |
-- | purerl note: Due to the nature of the BEAM platform Lazy values
-- | are not in fact lazy with the Erlang backend, but simple thunks, i.e.
-- | will be recomputed each time they are required.
foreign import data Lazy :: Type -> Type
type role Lazy representational
-- | Defer a computation, creating a `Lazy` value.
foreign import defer :: forall a. (Unit -> a) -> Lazy a
-- | Force evaluation of a `Lazy` value.
foreign import force :: forall a. Lazy a -> a
instance semiringLazy :: Semiring a => Semiring (Lazy a) where
add a b = defer \_ -> force a + force b
zero = defer \_ -> zero
mul a b = defer \_ -> force a * force b
one = defer \_ -> one
instance ringLazy :: Ring a => Ring (Lazy a) where
sub a b = defer \_ -> force a - force b
instance commutativeRingLazy :: CommutativeRing a => CommutativeRing (Lazy a)
instance euclideanRingLazy :: EuclideanRing a => EuclideanRing (Lazy a) where
degree = degree <<< force
div a b = defer \_ -> force a / force b
mod a b = defer \_ -> force a `mod` force b
instance eqLazy :: Eq a => Eq (Lazy a) where
eq x y = (force x) == (force y)
derive instance eq1Lazy :: Eq1 Lazy
instance ordLazy :: Ord a => Ord (Lazy a) where
compare x y = compare (force x) (force y)
derive instance ord1Lazy :: Ord1 Lazy
instance boundedLazy :: Bounded a => Bounded (Lazy a) where
top = defer \_ -> top
bottom = defer \_ -> bottom
instance semigroupLazy :: Semigroup a => Semigroup (Lazy a) where
append a b = defer \_ -> force a <> force b
instance monoidLazy :: Monoid a => Monoid (Lazy a) where
mempty = defer \_ -> mempty
instance heytingAlgebraLazy :: HeytingAlgebra a => HeytingAlgebra (Lazy a) where
ff = defer \_ -> ff
tt = defer \_ -> tt
implies a b = implies <$> a <*> b
conj a b = conj <$> a <*> b
disj a b = disj <$> a <*> b
not a = not <$> a
instance booleanAlgebraLazy :: BooleanAlgebra a => BooleanAlgebra (Lazy a)
instance functorLazy :: Functor Lazy where
map f l = defer \_ -> f (force l)
instance functorWithIndexLazy :: FunctorWithIndex Unit Lazy where
mapWithIndex f = map $ f unit
instance foldableLazy :: Foldable Lazy where
foldr f z l = f (force l) z
foldl f z l = f z (force l)
foldMap f l = f (force l)
instance foldableWithIndexLazy :: FoldableWithIndex Unit Lazy where
foldrWithIndex f = foldr $ f unit
foldlWithIndex f = foldl $ f unit
foldMapWithIndex f = foldMap $ f unit
instance foldable1Lazy :: Foldable1 Lazy where
foldMap1 f l = f (force l)
foldr1 _ l = force l
foldl1 _ l = force l
instance traversableLazy :: Traversable Lazy where
traverse f l = defer <<< const <$> f (force l)
sequence l = defer <<< const <$> force l
instance traversableWithIndexLazy :: TraversableWithIndex Unit Lazy where
traverseWithIndex f = traverse $ f unit
instance traversable1Lazy :: Traversable1 Lazy where
traverse1 f l = defer <<< const <$> f (force l)
sequence1 l = defer <<< const <$> force l
instance invariantLazy :: Invariant Lazy where
imap = imapF
instance applyLazy :: Apply Lazy where
apply f x = defer \_ -> force f (force x)
instance applicativeLazy :: Applicative Lazy where
pure a = defer \_ -> a
instance bindLazy :: Bind Lazy where
bind l f = defer \_ -> force $ f (force l)
instance monadLazy :: Monad Lazy
instance extendLazy :: Extend Lazy where
extend f x = defer \_ -> f x
instance comonadLazy :: Comonad Lazy where
extract = force
instance showLazy :: Show a => Show (Lazy a) where
show x = "(defer \\_ -> " <> show (force x) <> ")"
instance lazyLazy :: CL.Lazy (Lazy a) where
defer f = defer \_ -> force (f unit)