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

    {- |
       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
    $ \ x :: 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 f :: 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
    >>^ (\ x :: 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 f :: 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
    >>. \ x :: [c]
    x -> (c -> ()) -> [c] -> ()
    forall a. (a -> ()) -> [a] -> ()
    rlnf c -> ()
    forall a. WNFData a => a -> ()
    rwnf [c]
    x () -> [c] -> [c]
    forall a b. a -> b -> b
    `seq` [c]
    x
        {-# INLINE rwnfA #-}

        rwnf2A                      :: (WNFData c) => a b c -> a b c
        rwnf2A f :: 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
    >>. \ x :: [c]
    x -> (c -> ()) -> [c] -> ()
    forall a. (a -> ()) -> [a] -> ()
    rlnf c -> ()
    forall a. WNFData a => a -> ()
    rwnf2 [c]
    x () -> [c] -> [c]
    forall a b. a -> b -> b
    `seq` [c]
    x
        {-# INLINE rwnf2A #-}

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