scc-0.6: Control/Concurrent/SCC/Coercions.hs
{-
Copyright 2009-2010 Mario Blazevic
This file is part of the Streaming Component Combinators (SCC) project.
The SCC project is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
version.
SCC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with SCC. If not, see
<http://www.gnu.org/licenses/>.
-}
-- | This module defines class 'Coercible' and its instances.
{-# LANGUAGE Rank2Types, ScopedTypeVariables, MultiParamTypeClasses,
FlexibleContexts, FlexibleInstances, IncoherentInstances #-}
{-# OPTIONS_HADDOCK hide #-}
module Control.Concurrent.SCC.Coercions
(
-- * Coercible class
Coercible(..),
-- * Splitter isomorphism
adaptSplitter
)
where
import Prelude hiding ((.))
import Control.Category ((.))
import Control.Monad (liftM)
import Data.Text (Text, pack, unpack)
import Control.Monad.Coroutine
import Control.Monad.Parallel (MonadParallel(..))
import Control.Concurrent.SCC.Streams
import Control.Concurrent.SCC.Types
-- | Two streams of 'Coercible' types can be unambigously converted one to another.
class Coercible x y where
-- | A 'Transducer' that converts a stream of one type to another.
coerce :: Monad m => Transducer m x y
adaptConsumer :: Monad m => Consumer m y r -> Consumer m x r
adaptConsumer consumer = isolateConsumer $ \source-> liftM snd $ pipe (transduce coerce source) (consume consumer)
adaptProducer :: Monad m => Producer m x r -> Producer m y r
adaptProducer producer = isolateProducer $ \sink-> liftM fst $ pipe (produce producer) (flip (transduce coerce) sink)
instance Coercible x x where
coerce = Transducer pour
adaptConsumer = id
adaptProducer = id
instance Coercible Char Text where
coerce = Transducer (mapStreamChunks ((:[]) . pack))
instance Coercible Text Char where
coerce = statelessTransducer unpack
instance Coercible x y => Coercible [x] y where
coerce = coerce . statelessTransducer id
instance Coercible x y => Coercible (Markup b x) y where
coerce = coerce . statelessTransducer unmark
where unmark (Content x) = [x]
unmark (Markup _) = []
-- | Adjusts the argument splitter to split the stream of a data type 'Isomorphic' to the type it was meant to split.
adaptSplitter :: forall m x y b. (Monad m, Coercible x y, Coercible y x) => Splitter m x b -> Splitter m y b
adaptSplitter sx =
isolateSplitter $ \source true false edge->
pipe
(transduce coerce source)
(\source'->
pipe
(\true'->
pipe
(\false'-> split sx source' true' false' edge)
(flip (transduce coerce) false))
(flip (transduce coerce) true))
>> return ()