forked from purescript/purescript-prelude
/
Generic.purs
51 lines (40 loc) · 2.26 KB
/
Generic.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
module Data.Semiring.Generic where
import Prelude
import Data.Generic.Rep (class Generic, Argument(..), Constructor(..), NoArguments(..), Product(..), from, to)
class GenericSemiring a where
genericAdd' :: a -> a -> a
genericZero' :: a
genericMul' :: a -> a -> a
genericOne' :: a
instance genericSemiringNoArguments :: GenericSemiring NoArguments where
genericAdd' _ _ = NoArguments
genericZero' = NoArguments
genericMul' _ _ = NoArguments
genericOne' = NoArguments
instance genericSemiringArgument :: Semiring a => GenericSemiring (Argument a) where
genericAdd' (Argument x) (Argument y) = Argument (add x y)
genericZero' = Argument zero
genericMul' (Argument x) (Argument y) = Argument (mul x y)
genericOne' = Argument one
instance genericSemiringProduct :: (GenericSemiring a, GenericSemiring b) => GenericSemiring (Product a b) where
genericAdd' (Product a1 b1) (Product a2 b2) = Product (genericAdd' a1 a2) (genericAdd' b1 b2)
genericZero' = Product genericZero' genericZero'
genericMul' (Product a1 b1) (Product a2 b2) = Product (genericMul' a1 a2) (genericMul' b1 b2)
genericOne' = Product genericOne' genericOne'
instance genericSemiringConstructor :: GenericSemiring a => GenericSemiring (Constructor name a) where
genericAdd' (Constructor a1) (Constructor a2) = Constructor (genericAdd' a1 a2)
genericZero' = Constructor genericZero'
genericMul' (Constructor a1) (Constructor a2) = Constructor (genericMul' a1 a2)
genericOne' = Constructor genericOne'
-- | A `Generic` implementation of the `zero` member from the `Semiring` type class.
genericZero :: forall a rep. Generic a rep => GenericSemiring rep => a
genericZero = to genericZero'
-- | A `Generic` implementation of the `one` member from the `Semiring` type class.
genericOne :: forall a rep. Generic a rep => GenericSemiring rep => a
genericOne = to genericOne'
-- | A `Generic` implementation of the `add` member from the `Semiring` type class.
genericAdd :: forall a rep. Generic a rep => GenericSemiring rep => a -> a -> a
genericAdd x y = to $ from x `genericAdd'` from y
-- | A `Generic` implementation of the `mul` member from the `Semiring` type class.
genericMul :: forall a rep. Generic a rep => GenericSemiring rep => a -> a -> a
genericMul x y = to $ from x `genericMul'` from y