hnix/Nix/Utils.hs

51 lines
1.3 KiB
Haskell
Raw Normal View History

{-# LANGUAGE CPP #-}
module Nix.Utils (module Nix.Utils, module X) where
2018-03-29 00:00:28 +02:00
import Control.Monad
import Control.Monad.Fix
2018-03-29 00:00:28 +02:00
import Data.Fix
-- #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
2018-03-29 00:00:28 +02:00
(&) :: 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
2018-03-29 00:00:28 +02:00
-- | 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 :: (Monoid b, Applicative s, Traversable t)
=> (t a -> a)
-> ((Fix t -> (b, s a)) -> Fix t -> (b, s a))
-> Fix t -> (b, s a)
adi f g = g (go . traverse (adi f g) . unFix)
where
go = fmap (fmap f . sequenceA)
adiM :: (Monoid b, Applicative s, Traversable s, Traversable t, Monad m)
=> (t a -> m a)
-> ((Fix t -> m (b, s a)) -> Fix t -> m (b, s a))
-> Fix t -> m (b, s a)
adiM f g = g ((go <=< traverse (adiM f g)) . unFix)
where
go = traverse (traverse f . sequenceA) . sequenceA