packages feed

automaton-1.5: src/Data/Automaton/Recursive.hs

{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}

module Data.Automaton.Recursive where

-- base
import Control.Applicative (Alternative)
import Control.Arrow
import Control.Category
import Prelude hiding (id, (.))

-- transformers
import Control.Monad.Trans.Reader

-- automaton
import Data.Automaton
import Data.Stream.Optimized qualified as StreamOptimized
import Data.Stream.Recursive qualified as StreamRecursive

{- | Automata in direct recursive encoding.

This type is isomorphic to @MSF@ from @dunai@.
-}
newtype Recursive m a b = Recursive {getRecursive :: StreamRecursive.Recursive (ReaderT a m) b}
  deriving newtype (Functor, Applicative, Alternative)

instance (Monad m) => Category (Recursive m) where
  id = toRecursive id
  f1 . f2 = toRecursive $ fromRecursive f1 . fromRecursive f2

instance (Monad m) => Arrow (Recursive m) where
  arr = toRecursive . arr
  first = toRecursive . first . fromRecursive

toRecursive :: (Functor m) => Automaton m a b -> Recursive m a b
toRecursive (Automaton automaton) = Recursive $ StreamOptimized.toRecursive automaton

fromRecursive :: Recursive m a b -> Automaton m a b
fromRecursive Recursive {getRecursive} = Automaton $ StreamOptimized.fromRecursive getRecursive