From bbfe463f0aa754a036439808d3b289d74f46a8bf Mon Sep 17 00:00:00 2001 From: Adithya Kumar Date: Fri, 22 Jan 2021 07:22:15 +0530 Subject: [PATCH] Add Streamly.Internal.Data.Fold.Tee --- Changelog.md | 2 + src/Streamly/Internal/Data/Fold/Tee.hs | 51 ++++++++++++++++++++++++++ streamly.cabal | 1 + 3 files changed, 54 insertions(+) create mode 100644 src/Streamly/Internal/Data/Fold/Tee.hs diff --git a/Changelog.md b/Changelog.md index 1efe36cab..0318b6730 100644 --- a/Changelog.md +++ b/Changelog.md @@ -84,6 +84,8 @@ * A bug was fixed in the conversion of MicroSecond64 and MilliSecond64 (commit e5119626) * Bug fix: classifySessionsBy now flushes sessions at the end and terminates. +* `Streamly.Internal.Data.Fold.Tee` module added for folds with tee-like + applicative behaviour. ## 0.7.2 diff --git a/src/Streamly/Internal/Data/Fold/Tee.hs b/src/Streamly/Internal/Data/Fold/Tee.hs new file mode 100644 index 000000000..a73c4f787 --- /dev/null +++ b/src/Streamly/Internal/Data/Fold/Tee.hs @@ -0,0 +1,51 @@ +-- | +-- Module : Streamly.Internal.Data.Fold.Tee +-- Copyright : (c) 2020 Composewell Technologies +-- License : BSD-3-Clause +-- Maintainer : streamly@composewell.com +-- Stability : experimental +-- Portability : GHC +-- +module Streamly.Internal.Data.Fold.Tee + ( Tee(..) + , fromFold + , toFold + ) +where + +import Data.Coerce (coerce) +import Streamly.Internal.Data.Fold.Types (Fold) + +import qualified Streamly.Internal.Data.Fold.Types as Fold + +-- | The type @Tee m a b@ represents a left fold over an input stream of values +-- of type @a@ to a single value of type @b@ in 'Monad' @m@. +-- +-- @Tee@ is a wrapper over 'Fold' that uses 'teeWith' to define the applicative +-- instance. +-- +-- /Internal/ +newtype Tee m a b = + Tee { runTee :: Fold m a b } + deriving (Functor) + +-- | Convert a 'Tee' to 'Fold'. +{-# INLINE toFold #-} +toFold :: Tee m a b -> Fold m a b +toFold = coerce + +-- | Convert a 'Fold' to 'Tee'. +{-# INLINE fromFold #-} +fromFold :: Fold m a b -> Tee m a b +fromFold = coerce + +-- | The 'Tee' resulting from '<*>' distributes its input to both the argument +-- 'Tee's and combines their output using function application. +-- +instance Monad m => Applicative (Tee m a) where + + {-# INLINE pure #-} + pure a = fromFold (Fold.yield a) + + {-# INLINE (<*>) #-} + (<*>) a b = fromFold (Fold.teeWith ($) (toFold a) (toFold b)) diff --git a/streamly.cabal b/streamly.cabal index bb60e4717..b2f7b785d 100644 --- a/streamly.cabal +++ b/streamly.cabal @@ -468,6 +468,7 @@ library -- streamly-core , Streamly.Internal.Data.Unfold + , Streamly.Internal.Data.Fold.Tee , Streamly.Internal.Data.Fold , Streamly.Internal.Data.Sink , Streamly.Internal.Data.Parser