forked from parsonsmatt/prairie
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Prairie.hs
98 lines (83 loc) · 2.55 KB
/
Prairie.hs
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
-- | A library for first-class record fields.
--
-- @since 0.0.1.0
module Prairie
( module Prairie.Class
, module Prairie.Update
, module Prairie.Diff
, module Prairie.Fold
, module Prairie.Traverse
, module Prairie.Zip
, module Prairie.TH
, module Prairie.Semigroup
, module Prairie.Monoid
--
, Prairie (Prairie)
, type (~>)
, prairie
, distribute
, tabulate
, components
, Prairie.zipWith
, Prairie.unzip
, constants
, toList
, labelled
) where
import Prairie.Class
import Prairie.Diff
import Prairie.Fold
import Prairie.Monoid
import Prairie.Semigroup
import Prairie.TH
import Prairie.Traverse
import Prairie.Update
import Prairie.Zip
--
import Control.Lens
import Data.Functor.Const
import Data.Functor.Identity
import Data.Functor.Product
import Data.Kind
import Data.Text (Text)
import GHC.Records
newtype Prairie rec f = Prairie (forall ty. Field rec ty -> f ty)
instance (SymbolToField sym rec ty) => HasField sym (Prairie rec f) (f ty) where
getField (Prairie f) = f (symbolToField @sym)
type f ~> g = forall x. f x -> g x
infixr 9 ~>
prairie :: (Record rec) => Iso' rec (Prairie rec Identity)
prairie = iso (distribute . Identity) (runIdentity . tabulate)
distribute :: (Record rec, Functor f) => f rec -> Prairie rec f
distribute frec = Prairie \field -> getRecordField field <$> frec
tabulate :: (Record rec, Applicative f) => Prairie rec f -> f rec
tabulate (Prairie f) = tabulateRecordA f
components ::
(Record rec) => (forall x. f x -> g x) -> Prairie rec f -> Prairie rec g
components nat (Prairie f) = Prairie (nat . f)
zipWith ::
(Record rec) =>
(forall x. f x -> g x -> h x) ->
(Prairie rec f -> Prairie rec g -> Prairie rec h)
zipWith nat (Prairie f) (Prairie g) = Prairie (liftA2 nat f g)
zip ::
(Record rec) => Prairie rec f -> Prairie rec g -> Prairie rec (Product f g)
zip = Prairie.zipWith Pair
unzip ::
(Record rec) => Prairie rec (Product f g) -> (Prairie rec f, Prairie rec g)
unzip (Prairie p) =
( Prairie \field -> let Pair f _ = p field in f
, Prairie \field -> let Pair _ g = p field in g
)
constants ::
forall x rec.
(Record rec) =>
(forall ty. Field rec ty -> x) ->
Prairie rec (Const x)
constants f = Prairie \field -> Const (f field)
toList :: forall x rec. (Record rec) => Prairie rec (Const x) -> [x]
toList (Prairie f) = getConst . tabulate $ constants \field -> [getConst $ f field]
labelled ::
forall x rec. (Record rec) => Prairie rec (Const x) -> [(Text, x)]
labelled (Prairie values) = getConst . tabulate $ constants \field ->
[(recordFieldLabel field, getConst $ values field)]