-
Notifications
You must be signed in to change notification settings - Fork 0
/
PFLP.curry
103 lines (71 loc) · 2.16 KB
/
PFLP.curry
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
{-# OPTIONS_CYMAKE -X TypeClassExtensions #-}
module PFLP where
import SetFunctions (foldValues,set0)
infixl 4 <*>
infixl 4 <$>
infixl 4 >>>=
data Probability = Prob Float
deriving (Eq,Ord)
prob :: Float -> Probability
prob val
| val <= 1.0 && val >= 0.0 = Prob val
| otherwise = error "prob: the probability needs to range between 0.0 and 1.0"
data Dist a = Dist a Probability
deriving (Eq,Ord)
dist :: a -> Float -> Dist a
dist x prob
| prob <= 1.0 && prob >= 0.0 = Dist x (Prob prob)
| otherwise = error "dist: the probability needs to range between 0.0 and 1.0"
sumDist :: Dist a -> Probability
sumDist dists = probability $
foldValues (\ (Dist x q1) (Dist _ q2) -> Dist x (q1 + q2))
fail
(set0 dists)
filterDist :: (a -> Bool) -> Dist a -> Dist a
filterDist p d@(Dist v _) | p v = d
pure :: a -> Dist a
pure x = Dist x 1.0
(<*>) :: Dist (a -> b) -> Dist a -> Dist b
Dist f p <*> Dist x q = Dist (f x) (p*q)
(>>>=) :: Dist a -> (a -> Dist b) -> Dist b
Dist a p >>>= f =
let Dist b p' = f a
in Dist b (p * p')
-- ----------------------
-- Auxiliary Functions
-- ----------------------
-- Applicative "instance"
(<$>) :: (a -> b) -> Dist a -> Dist b
(<$>) f dA = pure f <*> dA
(*>) :: Dist a -> Dist b -> Dist b
dA *> dB = const id <$> dA <*> dB
(<*) :: Dist a -> Dist b -> Dist a
dA <* dB = const <$> dA <*> dB
sequenceA :: [Dist a] -> Dist [a]
sequenceA = traverse id
traverse :: (a -> Dist b) -> [a] -> Dist [b]
traverse f = foldr (liftA2 (:) . f) (pure [])
liftA2 :: (a -> b -> c) -> Dist a -> Dist b -> Dist c
liftA2 f dA dB = f <$> dA <*> dB
-- Num instance
instance Num Probability where
Prob x + Prob y = prob (x + y)
Prob x * Prob y = prob (x * y)
fromInteger x = prob (fromInteger x)
instance Fractional Probability where
Prob x / Prob y = prob (x / y)
fromFloat x = prob x
-- Smart constructors
certainly :: a -> Dist a
certainly x = Dist x 1.0
uncertainly :: a -> Dist a
uncertainly x = Dist x 0.0
fail :: Dist a
fail = Dist failed 0.0
-- Selector functions
unP :: Probability -> Float
unP (Prob f) = f
value :: Dist a -> a
value (Dist x _) = x
probability :: Dist a -> Probability
probability (Dist _ p) = p