-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFDerive.hs
85 lines (64 loc) · 1.76 KB
/
FDerive.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
{-# LANGUAGE DeriveFunctor #-}
module FDerive
( match
, emptySet
, emptyString
, character
, concat
, zeroOrMore
, or
) where
import Prelude hiding (concat, or)
import Data.Functor.Foldable (cata, unfix, Fix(..), para)
type Regex = Fix RegexF
data RegexF r = EmptySet
| EmptyString
| Character Char
| Concat r r
| ZeroOrMore r
| Or r r
deriving Functor
emptySet :: Regex
emptySet = Fix EmptySet
emptyString :: Regex
emptyString = Fix EmptyString
character :: Char -> Regex
character c = Fix (Character c)
concat :: Regex -> Regex -> Regex
concat a b = Fix (Concat a b)
zeroOrMore :: Regex -> Regex
zeroOrMore a = Fix (ZeroOrMore a)
or :: Regex -> Regex -> Regex
or a b = Fix (Or a b)
type Algebra f r = f r -> r
type NullableAlgebra = Algebra RegexF Bool
nullable' :: NullableAlgebra
nullable' EmptySet = False
nullable' EmptyString = True
nullable' Character{} = False
nullable' (Concat a b) = a && b
nullable' ZeroOrMore{} = True
nullable' (Or a b) = a || b
-- cata :: (RegexF Bool -> Bool) -> Regex -> Bool
nullable :: Regex -> Bool
nullable = cata nullable'
type RAlgebra f r = f (Fix f, r) -> r
type DeriveRAlgebra = RAlgebra RegexF Regex
deriv' :: Char -> DeriveRAlgebra
deriv' _ EmptyString = emptySet
deriv' _ EmptySet = emptySet
deriv' c (Character a) = if a == c
then emptyString else emptySet
deriv' c (Concat (r, dr) (s, ds)) =
if nullable r
then (dr `concat` s) `or` ds
else dr `concat` s
deriv' _ (ZeroOrMore (dr, r)) =
dr `concat` zeroOrMore r
deriv' _ (Or (_, dr) (_, ds)) =
dr `or` ds
-- para :: (RegexF (Regex, Regex) -> Regex) -> Regex -> Regex
deriv :: Regex -> Char -> Regex
deriv expr c = para (deriv' c) expr
match :: Regex -> String -> Bool
match expr string = nullable (foldl deriv expr string)