packages feed

symantic-base-0.3.0.20211007: src/Symantic/Optimize.hs

module Symantic.Optimize where

import Data.Bool (Bool)
import qualified Data.Function as Fun

import Symantic.Class
import Symantic.Data

-- | Beta-reduce the left-most outer-most lambda abstraction (aka. normal-order reduction),
-- but to avoid duplication of work, only those manually marked
-- as using their variable at most once.
--
-- DOC: Demonstrating Lambda Calculus Reduction, Peter Sestoft, 2001,
-- https://www.itu.dk/people/sestoft/papers/sestoft-lamreduce.pdf
normalOrderReduction :: forall repr a.
  Abstractable repr =>
  IfThenElseable repr =>
  SomeData repr a -> SomeData repr a
normalOrderReduction = nor
  where
  -- | normal-order reduction
  nor :: SomeData repr b -> SomeData repr b
  nor = \case
    Data (Lam f) -> lam (nor Fun.. f)
    Data (Lam1 f) -> lam1 (nor Fun.. f)
    Data (x :@ y) -> case whnf x of
      Data (Lam1 f) -> nor (f y)
      x' -> nor x' .@ nor y
    Data (IfThenElse test ok ko) ->
      case nor test of
        Data (Constant b :: Data (Constantable Bool) repr Bool) ->
          if b then nor ok else nor ko
        t -> ifThenElse (nor t) (nor ok) (nor ko)
    x -> x
  -- | weak-head normal-form
  whnf :: SomeData repr b -> SomeData repr b
  whnf = \case
    Data (x :@ y) -> case whnf x of
      Data (Lam1 f) -> whnf (f y)
      x' -> x' .@ y
    x -> x