-- ------------------------------------------------------------

{- |
   Module     : Control.Arrow.ArrowNF
   Copyright  : Copyright (C) 2011 Uwe Schmidt
   License    : MIT

   Maintainer : Uwe Schmidt (uwe\@fh-wedel.de)
   Stability  : experimental
   Portability: non-portable

   Arrows for evaluation of normal form results

-}

-- ------------------------------------------------------------

module Control.Arrow.ArrowNF
where

import           Control.Arrow
import           Control.Arrow.ArrowList

import           Control.DeepSeq
import           Control.FlatSeq

-- |
-- complete evaluation of an arrow result using 'Control.DeepSeq'
--
-- this is sometimes useful for preventing space leaks, especially after reading
-- and validation of a document, all DTD stuff is not longer in use and can be
-- recycled by the GC.

strictA :: (Arrow a, NFData b) => a b b
strictA :: a b b
strictA = (b -> b) -> a b b
forall (a :: * -> * -> *) b c. Arrow a => (b -> c) -> a b c
arr ((b -> b) -> a b b) -> (b -> b) -> a b b
forall a b. (a -> b) -> a -> b
$ \ b
x -> b -> b -> b
forall a b. NFData a => a -> b -> b
deepseq b
x b
x

class (Arrow a) => ArrowNF a where
    rnfA                        :: (NFData c) => a b c -> a b c
    rnfA a b c
f                      = a b c
f a b c -> (c -> c) -> a b c
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> (c -> d) -> a b d
>>^ (\ c
x -> c -> c -> c
forall a b. NFData a => a -> b -> b
deepseq c
x c
x)
    {-# INLINE rnfA #-}

-- |
-- partial evaluation of an arrow result using 'Control.FlatSeq'
--
-- There are two arrows with force the partial evaluation. By convention
-- the 2. should be less lazy than the 1.
--
-- These arrows are sometimes useful for preventing space leaks, especially when parsing
-- complex data structures. In many cases the evaluated AST is more space efficient
-- than the unevaluaded with a lot of closures.

class (Arrow a, ArrowList a) => ArrowWNF a where
    rwnfA                       :: (WNFData c) => a b c -> a b c
    rwnfA a b c
f                     = a b c
f a b c -> ([c] -> [c]) -> a b c
forall (a :: * -> * -> *) b c d.
ArrowList a =>
a b c -> ([c] -> [d]) -> a b d
>>. \ [c]
x -> (c -> ()) -> [c] -> ()
forall a. (a -> ()) -> [a] -> ()
rlnf c -> ()
forall a. WNFData a => a -> ()
rwnf [c]
x () -> [c] -> [c]
`seq` [c]
x
    {-# INLINE rwnfA #-}

    rwnf2A                      :: (WNFData c) => a b c -> a b c
    rwnf2A a b c
f                    = a b c
f a b c -> ([c] -> [c]) -> a b c
forall (a :: * -> * -> *) b c d.
ArrowList a =>
a b c -> ([c] -> [d]) -> a b d
>>. \ [c]
x -> (c -> ()) -> [c] -> ()
forall a. (a -> ()) -> [a] -> ()
rlnf c -> ()
forall a. WNFData a => a -> ()
rwnf2 [c]
x () -> [c] -> [c]
`seq` [c]
x
    {-# INLINE rwnf2A #-}

-- ------------------------------------------------------------