{-# LANGUAGE QuasiQuotes #-}

-- | Definitions found in Haskell's "Data.Function".
--
-- This module should be imported qualified to avoid clashes with standard
-- Haskell definitions.
module Stg.Prelude.Function (
    seq,
    id,
    const,
    compose,
    fix,
) where



import Prelude ()

import Stg.Language           (Program)
import Stg.Parser.QuasiQuoter



seq, id, const, compose, fix :: Program



-- | Finally I can define 'Prelude.seq' directly! :-)
--
-- Note that this function is less powerful than GHC's 'Prelude.seq', since  STG
-- does not have a rule to force functions, only expressions that reduce to an
-- algebraic or primitive value. This leads to the fact that STG's @seq@ is less
-- powerful than Haskell's, since in Haskell
--
-- @
-- seq (const ()) () = ()
-- @
--
-- whereas in the STG
--
-- @
-- constUnit = \(x) -> Unit ();
-- seq (constUnit, Unit) = ERROR
-- @
seq = [program| seq = \x y -> case x of default -> y |]

-- | Identity function.
--
-- @
-- id : a -> a
-- @
id = [program| id = \x -> x |]

-- | Constant function.
--
-- @
-- Const : a -> b -> a
-- @
const = [program| const = \x y -> x |]

-- | Function composition.
--
-- @
-- compose : (b -> c) -> (a -> b) -> a -> c
-- @
compose = [program|
    compose = \f g x ->
        let gx = \(g x) -> g x
        in f gx
    |]

-- | The fixed point combinator.
--
-- @
-- fix : (a -> a) -> a
-- @
fix = [program| fix = \f -> letrec x = \(f x) => f x in x |]