    -----------------------------------------------------------------------------
    -- |
    -- Module      :  Data.Strict.Tuple
    -- Copyright   :  (c) 2006-2007 Roman Leshchinskiy
    -- License     :  BSD-style (see the file LICENSE)
    --
    -- Maintainer  :  Roman Leshchinskiy <rl@cse.unsw.edu.au>
    -- Stability   :  experimental
    -- Portability :  portable
    --
    -- Strict pairs.
    --
    -- Same as regular Haskell pairs, but @(x :*: _|_) = (_|_ :*: y) = _|_@
    --
    -----------------------------------------------------------------------------

    {-# OPTIONS_GHC -fglasgow-exts #-}

    module Data.Strict.Tuple (
        Pair(..)
    #ifndef __HADDOCK__
    #ifdef __GLASGOW_HASKELL__
      , (:!:)
    #endif
    #endif
      , fst
      , snd
      , curry
      , uncurry
    ) where

    import Prelude hiding( fst, snd, curry, uncurry )
    import Data.Array (Ix)

    infixl 2 :!:

    -- | The type of strict pairs.
    data Pair a b = !a :!: !b deriving(Pair a b -> Pair a b -> Bool
    (Pair a b -> Pair a b -> Bool)
    -> (Pair a b -> Pair a b -> Bool) -> Eq (Pair a b)
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    forall a b. (Eq a, Eq b) => Pair a b -> Pair a b -> Bool
    /= :: Pair a b -> Pair a b -> Bool
    $c/= :: forall a b. (Eq a, Eq b) => Pair a b -> Pair a b -> Bool
    == :: Pair a b -> Pair a b -> Bool
    $c== :: forall a b. (Eq a, Eq b) => Pair a b -> Pair a b -> Bool
    Eq, Eq (Pair a b)
    Eq (Pair a b) =>
    (Pair a b -> Pair a b -> Ordering)
    -> (Pair a b -> Pair a b -> Bool)
    -> (Pair a b -> Pair a b -> Bool)
    -> (Pair a b -> Pair a b -> Bool)
    -> (Pair a b -> Pair a b -> Bool)
    -> (Pair a b -> Pair a b -> Pair a b)
    -> (Pair a b -> Pair a b -> Pair a b)
    -> Ord (Pair a b)
    Pair a b -> Pair a b -> Bool
    Pair a b -> Pair a b -> Ordering
    Pair a b -> Pair a b -> Pair a b
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    forall {a} {b}. (Ord a, Ord b) => Eq (Pair a b)
    forall a b. (Ord a, Ord b) => Pair a b -> Pair a b -> Bool
    forall a b. (Ord a, Ord b) => Pair a b -> Pair a b -> Ordering
    forall a b. (Ord a, Ord b) => Pair a b -> Pair a b -> Pair a b
    min :: Pair a b -> Pair a b -> Pair a b
    $cmin :: forall a b. (Ord a, Ord b) => Pair a b -> Pair a b -> Pair a b
    max :: Pair a b -> Pair a b -> Pair a b
    $cmax :: forall a b. (Ord a, Ord b) => Pair a b -> Pair a b -> Pair a b
    >= :: Pair a b -> Pair a b -> Bool
    $c>= :: forall a b. (Ord a, Ord b) => Pair a b -> Pair a b -> Bool
    > :: Pair a b -> Pair a b -> Bool
    $c> :: forall a b. (Ord a, Ord b) => Pair a b -> Pair a b -> Bool
    <= :: Pair a b -> Pair a b -> Bool
    $c<= :: forall a b. (Ord a, Ord b) => Pair a b -> Pair a b -> Bool
    < :: Pair a b -> Pair a b -> Bool
    $c< :: forall a b. (Ord a, Ord b) => Pair a b -> Pair a b -> Bool
    compare :: Pair a b -> Pair a b -> Ordering
    $ccompare :: forall a b. (Ord a, Ord b) => Pair a b -> Pair a b -> Ordering
    $cp1Ord :: forall {a} {b}. (Ord a, Ord b) => Eq (Pair a b)
    Ord, Int -> Pair a b -> ShowS
    [Pair a b] -> ShowS
    Pair a b -> String
    (Int -> Pair a b -> ShowS)
    -> (Pair a b -> String) -> ([Pair a b] -> ShowS) -> Show (Pair a b)
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    forall a b. (Show a, Show b) => Int -> Pair a b -> ShowS
    forall a b. (Show a, Show b) => [Pair a b] -> ShowS
    forall a b. (Show a, Show b) => Pair a b -> String
    showList :: [Pair a b] -> ShowS
    $cshowList :: forall a b. (Show a, Show b) => [Pair a b] -> ShowS
    show :: Pair a b -> String
    $cshow :: forall a b. (Show a, Show b) => Pair a b -> String
    showsPrec :: Int -> Pair a b -> ShowS
    $cshowsPrec :: forall a b. (Show a, Show b) => Int -> Pair a b -> ShowS
    Show, ReadPrec [Pair a b]
    ReadPrec (Pair a b)
    Int -> ReadS (Pair a b)
    ReadS [Pair a b]
    (Int -> ReadS (Pair a b))
    -> ReadS [Pair a b]
    -> ReadPrec (Pair a b)
    -> ReadPrec [Pair a b]
    -> Read (Pair a b)
    forall a.
    (Int -> ReadS a)
    -> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
    forall a b. (Read a, Read b) => ReadPrec [Pair a b]
    forall a b. (Read a, Read b) => ReadPrec (Pair a b)
    forall a b. (Read a, Read b) => Int -> ReadS (Pair a b)
    forall a b. (Read a, Read b) => ReadS [Pair a b]
    readListPrec :: ReadPrec [Pair a b]
    $creadListPrec :: forall a b. (Read a, Read b) => ReadPrec [Pair a b]
    readPrec :: ReadPrec (Pair a b)
    $creadPrec :: forall a b. (Read a, Read b) => ReadPrec (Pair a b)
    readList :: ReadS [Pair a b]
    $creadList :: forall a b. (Read a, Read b) => ReadS [Pair a b]
    readsPrec :: Int -> ReadS (Pair a b)
    $creadsPrec :: forall a b. (Read a, Read b) => Int -> ReadS (Pair a b)
    Read, Pair a b
    Pair a b -> Pair a b -> Bounded (Pair a b)
    forall a. a -> a -> Bounded a
    forall a b. (Bounded a, Bounded b) => Pair a b
    maxBound :: Pair a b
    $cmaxBound :: forall a b. (Bounded a, Bounded b) => Pair a b
    minBound :: Pair a b
    $cminBound :: forall a b. (Bounded a, Bounded b) => Pair a b
    Bounded, Ord (Pair a b)
    Ord (Pair a b) =>
    ((Pair a b, Pair a b) -> [Pair a b])
    -> ((Pair a b, Pair a b) -> Pair a b -> Int)
    -> ((Pair a b, Pair a b) -> Pair a b -> Int)
    -> ((Pair a b, Pair a b) -> Pair a b -> Bool)
    -> ((Pair a b, Pair a b) -> Int)
    -> ((Pair a b, Pair a b) -> Int)
    -> Ix (Pair a b)
    (Pair a b, Pair a b) -> Int
    (Pair a b, Pair a b) -> [Pair a b]
    (Pair a b, Pair a b) -> Pair a b -> Bool
    (Pair a b, Pair a b) -> Pair a b -> Int
    forall a.
    Ord a =>
    ((a, a) -> [a])
    -> ((a, a) -> a -> Int)
    -> ((a, a) -> a -> Int)
    -> ((a, a) -> a -> Bool)
    -> ((a, a) -> Int)
    -> ((a, a) -> Int)
    -> Ix a
    forall {a} {b}. (Ix a, Ix b) => Ord (Pair a b)
    forall a b. (Ix a, Ix b) => (Pair a b, Pair a b) -> Int
    forall a b. (Ix a, Ix b) => (Pair a b, Pair a b) -> [Pair a b]
    forall a b.
    (Ix a, Ix b) =>
    (Pair a b, Pair a b) -> Pair a b -> Bool
    forall a b. (Ix a, Ix b) => (Pair a b, Pair a b) -> Pair a b -> Int
    unsafeRangeSize :: (Pair a b, Pair a b) -> Int
    $cunsafeRangeSize :: forall a b. (Ix a, Ix b) => (Pair a b, Pair a b) -> Int
    rangeSize :: (Pair a b, Pair a b) -> Int
    $crangeSize :: forall a b. (Ix a, Ix b) => (Pair a b, Pair a b) -> Int
    inRange :: (Pair a b, Pair a b) -> Pair a b -> Bool
    $cinRange :: forall a b.
    (Ix a, Ix b) =>
    (Pair a b, Pair a b) -> Pair a b -> Bool
    unsafeIndex :: (Pair a b, Pair a b) -> Pair a b -> Int
    $cunsafeIndex :: forall a b. (Ix a, Ix b) => (Pair a b, Pair a b) -> Pair a b -> Int
    index :: (Pair a b, Pair a b) -> Pair a b -> Int
    $cindex :: forall a b. (Ix a, Ix b) => (Pair a b, Pair a b) -> Pair a b -> Int
    range :: (Pair a b, Pair a b) -> [Pair a b]
    $crange :: forall a b. (Ix a, Ix b) => (Pair a b, Pair a b) -> [Pair a b]
    $cp1Ix :: forall {a} {b}. (Ix a, Ix b) => Ord (Pair a b)
    Ix)

    #ifndef __HADDOCK__
    #ifdef __GLASGOW_HASKELL__
    -- This gives a nicer syntax for the type but only works in GHC for now.
    type (:!:) = Pair
    #endif
    #endif

    -- | Extract the first component of a strict pair.
    fst :: Pair a b -> a
    fst :: Pair a b -> a
    fst (x :: a
    x :!: _) = a
    x

    -- | Extract the second component of a strict pair.
    snd :: Pair a b -> b
    snd :: Pair a b -> b
    snd (_ :!: y :: b
    y) = b
    y

    -- | Curry a function on strict pairs.
    curry :: (Pair a b -> c) -> a -> b -> c
    curry :: (Pair a b -> c) -> a -> b -> c
    curry f :: Pair a b -> c
    f x :: a
    x y :: b
    y = Pair a b -> c
    f (a
    x a -> b -> Pair a b
    forall a b. a -> b -> Pair a b
    :!: b
    y)

    -- | Convert a curried function to a function on strict pairs.
    uncurry :: (a -> b -> c) -> Pair a b -> c
    uncurry :: (a -> b -> c) -> Pair a b -> c
    uncurry f :: a -> b -> c
    f (x :: a
    x :!: y :: b
    y) = a -> b -> c
    f a
    x b
    y