packages feed

fastmemo-0.1.1: src/Data/Function/FastMemo/Class.hs

{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE EmptyCase #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE TypeOperators #-}

module Data.Function.FastMemo.Class (Memoizable (..)) where

import GHC.Generics

class Memoizable a where
  memoize :: (a -> b) -> a -> b
  default memoize :: (Generic a, GMemoize (Rep a)) => (a -> b) -> a -> b
  memoize f = gMemoize (f . to) . from

class GMemoize a where
  gMemoize :: (a p -> b) -> a p -> b

instance GMemoize f => GMemoize (M1 i c f) where
  gMemoize f = gMemoize (f . M1) . unM1

instance GMemoize V1 where
  gMemoize _f = \case {}

instance GMemoize U1 where
  gMemoize f = let fu = f U1 in \U1 -> fu

instance Memoizable c => GMemoize (K1 i c) where
  gMemoize f = memoize (f . K1) . unK1

instance (GMemoize a, GMemoize b) => GMemoize (a :*: b) where
  gMemoize f =
    let f' = gMemoize (\x -> gMemoize (\y -> f (x :*: y)))
     in \(x :*: y) -> f' x y

instance (GMemoize a, GMemoize b) => GMemoize (a :+: b) where
  gMemoize f =
    let fL = gMemoize (f . L1)
        fR = gMemoize (f . R1)
     in \case
          L1 x -> fL x
          R1 x -> fR x

instance (Memoizable a, Memoizable b) => Memoizable (a, b)