funflow-1.6.0: src/Control/Funflow/Class.hs
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeSynonymInstances #-}
-- | Defines a class for types which can be used as workflows.
--
-- In general, you should not need this functionality unless you are defining
-- your own flow types (perhaps to use a state transformer or similar), in
-- which case this allows you to work using the standard combinators in
-- Funflow and then define the mapping to 'Base.Flow'
--
-- For an example of use, see the module @Control.Funflow.Checkpoints@, which
-- defines a checkpointed flow.
module Control.Funflow.Class where
import Control.Arrow
import Control.Arrow.Free
import qualified Control.Funflow.Base as Base
import Control.Funflow.External
import Data.CAS.ContentHashable
import qualified Data.CAS.ContentStore as CS
import qualified Data.Profunctor.Cayley as P
import Data.Default (def)
import Path
class (Arrow arr, ArrowError ex arr) => ArrowFlow eff ex arr | arr -> eff ex where
-- | Create a flow from a pure function.
step' :: Base.Properties a b -> (a -> b) -> arr a b
-- | Create a flow from an IO action.
stepIO' :: Base.Properties a b -> (a -> IO b) -> arr a b
-- | Create an external task in the flow.
external :: (a -> ExternalTask) -> arr a CS.Item
-- | Create an external task with additional properties
external' :: Base.ExternalProperties a -> (a -> ExternalTask) -> arr a CS.Item
-- | Create a flow from a user-defined effect.
wrap' :: Base.Properties a b -> eff a b -> arr a b
-- | Create a flow which will write its incoming data to the store.
putInStore :: ContentHashable IO a => (Path Abs Dir -> a -> IO ()) -> arr a CS.Item
-- | Create a flow which will read data from the given store item.
getFromStore :: (Path Abs t -> IO a) -> arr (CS.Content t) a
-- | Perform some internal manipulation of the content store.
internalManipulateStore :: (CS.ContentStore -> a -> IO b) -> arr a b
instance ArrowFlow eff ex (Base.Flow eff ex) where
step' props = effect . Base.Step props
stepIO' props = effect . Base.StepIO props
external = effect . Base.External def
external' p td = effect $ Base.External p td
wrap' p eff = effect $ Base.Wrapped p eff
putInStore = effect . Base.PutInStore
getFromStore = effect . Base.GetFromStore
internalManipulateStore = effect . Base.InternalManipulateStore
-- | Create a flow from a pure function.
-- This is a variant on 'step'' which uses the default properties.
step :: ArrowFlow eff ex arr => (a -> b) -> arr a b
step = step' def
-- | Create a flow from an IO action.
-- This is a variant on 'stepIO'' which uses the default properties.
stepIO :: ArrowFlow eff ex arr => (a -> IO b) -> arr a b
stepIO = stepIO' def
wrap :: ArrowFlow eff ex arr => eff a b -> arr a b
wrap = wrap' def
instance ( Applicative app
, ArrowError ex (arr eff ex)
, ArrowFlow eff ex (arr eff ex) )
=> ArrowFlow eff ex (P.Cayley app (arr eff ex)) where
step' props f = P.Cayley . pure $ step' props f
stepIO' props f = P.Cayley . pure $ stepIO' props f
external f = P.Cayley . pure $ external f
external' props f = P.Cayley . pure $ external' props f
wrap' props eff = P.Cayley . pure $ wrap' props eff
putInStore f = P.Cayley . pure $ putInStore f
getFromStore f = P.Cayley . pure $ getFromStore f
internalManipulateStore f = P.Cayley . pure $ internalManipulateStore f