{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
module Datafix.FrameworkBuilder
( FrameworkBuilder
, buildFramework
) where
import Data.Primitive.Array
import Datafix.Common
import Datafix.Denotational
import Datafix.Explicit
import Datafix.NodeAllocator
newtype FrameworkBuilder m a
= FrameworkBuilder { unwrapFB :: NodeAllocator (ChangeDetector (Domain m), LiftedFunc (Domain m) m) a }
deriving (Functor, Applicative, Monad)
instance MonadDependency m => MonadDatafix (FrameworkBuilder m) where
type DepM (FrameworkBuilder m) = m
datafix cd func = FrameworkBuilder $ allocateNode $ \node -> do
let deref = dependOn @m node
(ret, transfer) <- unwrapFB (func deref)
return (ret, (cd, transfer))
buildFramework
:: forall m a
. MonadDependency m
=> (forall md . (MonadDatafix md, DepM md ~ m) => md a)
-> (a, Node, DataFlowFramework m)
buildFramework plan = (a, Node (sizeofArray arr - 1), prob)
where
prob = DFF (snd . indexArray arr . unwrapNode) (fst . indexArray arr . unwrapNode)
(a, arr) = runAllocator $ unwrapFB $ plan @(FrameworkBuilder m)