It's even nicer with Kleisli:
recognise' :: RE -> Kleisli [] String String
recognise' =
foldRE empty id ch (>>>) (<|>) (\p -> fix (\t -> id <|> (p >>> t))) where
ch c = Kleisli (\case x : xs | c == x -> [xs]; _ -> [])
**The Haskell programming language community.** Daily news and info about all things Haskell related: practical stuff, theory, types, libraries, jobs, patches, releases, events and conferences and more... ### Links - Get Started with Haskell
It's even nicer with Kleisli:
recognise' :: RE -> Kleisli [] String String
recognise' =
foldRE empty id ch (>>>) (<|>) (\p -> fix (\t -> id <|> (p >>> t))) where
ch c = Kleisli (\case x : xs | c == x -> [xs]; _ -> [])
Of course StateT
is perhaps more common and as elegant as Kleisli
:
recognise :: RE -> StateT String [] ()
recognise =
foldRE empty (pure ()) ch (*>) (<|>) (\p -> fix (\t -> p *> t <|> pure ())) where
ch c = StateT (\case x : xs | c == x -> [((), xs)]; _ -> [])
@jaror I’d deem it more elegant if there were any useful names in here eh
@mangoiv perhaps it is slightly easier to read like this?
data RE = Empty | Eps | Ch Char | App RE RE | Alt RE RE | Star RE
data REalg a = REalg
{ emp :: a
, eps :: a
, ch :: Char -> a
, app :: a -> a -> a
, alt :: a -> a -> a
, star :: a -> a
}
foldRE :: REalg a -> RE -> a
foldRE alg = go where
go = \case
Empty -> emp alg
Eps -> eps alg
Ch c -> ch alg c
App p q -> app alg (go p) (go q)
Alt p q -> alt alg (go p) (go q)
Star p -> star alg (go p)
recognise :: RE -> StateT String [] ()
recognise = foldRE REalg
{ emp = empty
, eps = pure ()
, ch = \c -> StateT (\case x : xs | c == x -> [((), xs)]; _ -> [])
, app = (*>)
, alt = (<|>)
, star = \p -> fix (\t -> p *> t <|> pure ())
}