{-# LANGUAGE CPP #-} {-# LANGUAGE ScopedTypeVariables #-} module Nix.Utils (module Nix.Utils, module X) where import Control.Monad import Control.Monad.Fix import Data.Fix import Data.Monoid (Endo) -- #define ENABLE_TRACING 1 #if ENABLE_TRACING import Debug.Trace as X #else import Prelude as X trace :: String -> a -> a trace = const id traceM :: Monad m => String -> m () traceM = const (return ()) #endif type DList a = Endo [a] (&) :: a -> (a -> c) -> c (&) = flip ($) loeb :: Functor f => f (f a -> a) -> f a loeb x = go where go = fmap ($ go) x loebM :: (MonadFix m, Traversable t) => t (t a -> m a) -> m (t a) loebM f = mfix $ \a -> mapM ($ a) f para :: (a -> [a] -> b -> b) -> b -> [a] -> b para f base = h where h [] = base h (x:xs) = f x xs (h xs) -- | adi is Abstracting Definitional Interpreters: -- -- https://arxiv.org/abs/1707.04755 -- -- Essentially, it does for evaluation what recursion schemes do for -- representation: allows threading layers through existing structure, only -- in this case through behavior. adi :: Traversable t => (t a -> a) -> ((Fix t -> a) -> Fix t -> a) -> Fix t -> a adi f g = g (f . fmap (adi f g) . unFix) adiM :: (Traversable t, Monad m) => (t a -> m a) -> ((Fix t -> m a) -> Fix t -> m a) -> Fix t -> m a adiM f g = g ((f <=< traverse (adiM f g)) . unFix)