{-# LANGUAGE QuantifiedConstraints #-}

module Bluefin.Internal.DslBuilder where

import Bluefin.Internal
import Bluefin.Internal.DslBuilderEffects
  ( DslBuilderEffects,
    dslBuilderEffects,
    runDslBuilderEffects,
  )

newtype Forall f r = MkForall {forall {k} {k} (f :: k -> k -> *) (r :: k).
Forall f r -> forall (es :: k). f es r
unForall :: forall es. f es r}

mkForall :: (forall es. f es r) -> Forall f r
mkForall :: forall {k} {k} (f :: k -> k -> *) (r :: k).
(forall (es :: k). f es r) -> Forall f r
mkForall = (forall (es :: k). f es r) -> Forall f r
forall {k} {k} (f :: k -> k -> *) (r :: k).
(forall (es :: k). f es r) -> Forall f r
MkForall

instance (forall es. Functor (f es)) => Functor (Forall f) where
  fmap :: forall a b. (a -> b) -> Forall f a -> Forall f b
fmap a -> b
f Forall f a
k = (forall (es :: k). f es b) -> Forall f b
forall {k} {k} (f :: k -> k -> *) (r :: k).
(forall (es :: k). f es r) -> Forall f r
MkForall ((a -> b) -> f es a -> f es b
forall a b. (a -> b) -> f es a -> f es b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f (Forall f a -> forall (es :: k). f es a
forall {k} {k} (f :: k -> k -> *) (r :: k).
Forall f r -> forall (es :: k). f es r
unForall Forall f a
k))

instance (forall es. Applicative (f es)) => Applicative (Forall f) where
  pure :: forall a. a -> Forall f a
pure a
x = (forall (es :: k). f es a) -> Forall f a
forall {k} {k} (f :: k -> k -> *) (r :: k).
(forall (es :: k). f es r) -> Forall f r
mkForall (a -> f es a
forall a. a -> f es a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
x)
  Forall f (a -> b)
f <*> :: forall a b. Forall f (a -> b) -> Forall f a -> Forall f b
<*> Forall f a
x = (forall (es :: k). f es b) -> Forall f b
forall {k} {k} (f :: k -> k -> *) (r :: k).
(forall (es :: k). f es r) -> Forall f r
mkForall (Forall f (a -> b) -> forall (es :: k). f es (a -> b)
forall {k} {k} (f :: k -> k -> *) (r :: k).
Forall f r -> forall (es :: k). f es r
unForall Forall f (a -> b)
f f es (a -> b) -> f es a -> f es b
forall a b. f es (a -> b) -> f es a -> f es b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Forall f a -> forall (es :: k). f es a
forall {k} {k} (f :: k -> k -> *) (r :: k).
Forall f r -> forall (es :: k). f es r
unForall Forall f a
x)

instance (forall es. Monad (f es)) => Monad (Forall f) where
  Forall f a
m >>= :: forall a b. Forall f a -> (a -> Forall f b) -> Forall f b
>>= a -> Forall f b
f = (forall (es :: k). f es b) -> Forall f b
forall {k} {k} (f :: k -> k -> *) (r :: k).
(forall (es :: k). f es r) -> Forall f r
mkForall ((forall (es :: k). f es b) -> Forall f b)
-> (forall (es :: k). f es b) -> Forall f b
forall a b. (a -> b) -> a -> b
$ do
    a
r <- Forall f a -> forall (es :: k). f es a
forall {k} {k} (f :: k -> k -> *) (r :: k).
Forall f r -> forall (es :: k). f es r
unForall Forall f a
m
    Forall f b -> forall (es :: k). f es b
forall {k} {k} (f :: k -> k -> *) (r :: k).
Forall f r -> forall (es :: k). f es r
unForall (a -> Forall f b
f a
r)

newtype DslBuilder h r
  = MkDslBuilder {forall (h :: Effects -> *) r.
DslBuilder h r -> Forall (DslBuilderEffects h) r
unMkDslBuilder :: Forall (DslBuilderEffects h) r}

runDslBuilder :: (Handle h) => h es -> DslBuilder h r -> Eff es r
runDslBuilder :: forall (h :: Effects -> *) (es :: Effects) r.
Handle h =>
h es -> DslBuilder h r -> Eff es r
runDslBuilder h es
h DslBuilder h r
f = h es -> DslBuilderEffects h es r -> Eff es r
forall (h :: Effects -> *) (es :: Effects) r.
h es -> DslBuilderEffects h es r -> Eff es r
runDslBuilderEffects h es
h (Forall (DslBuilderEffects h) r
-> forall (es :: Effects). DslBuilderEffects h es r
forall {k} {k} (f :: k -> k -> *) (r :: k).
Forall f r -> forall (es :: k). f es r
unForall (DslBuilder h r -> Forall (DslBuilderEffects h) r
forall (h :: Effects -> *) r.
DslBuilder h r -> Forall (DslBuilderEffects h) r
unMkDslBuilder DslBuilder h r
f))

dslBuilder :: (forall e. h e -> Eff e r) -> DslBuilder h r
dslBuilder :: forall (h :: Effects -> *) r.
(forall (e :: Effects). h e -> Eff e r) -> DslBuilder h r
dslBuilder forall (e :: Effects). h e -> Eff e r
k = Forall (DslBuilderEffects h) r -> DslBuilder h r
forall (h :: Effects -> *) r.
Forall (DslBuilderEffects h) r -> DslBuilder h r
MkDslBuilder ((forall (es :: Effects). DslBuilderEffects h es r)
-> Forall (DslBuilderEffects h) r
forall {k} {k} (f :: k -> k -> *) (r :: k).
(forall (es :: k). f es r) -> Forall f r
mkForall ((forall (e :: Effects). h e -> Eff (e :& es) r)
-> DslBuilderEffects h es r
forall (h :: Effects -> *) (es :: Effects) r.
(forall (e :: Effects). h e -> Eff (e :& es) r)
-> DslBuilderEffects h es r
dslBuilderEffects (Eff e r -> Eff (e :& es) r
forall (e :: Effects) (es :: Effects) r.
(e :> es) =>
Eff e r -> Eff es r
useImpl (Eff e r -> Eff (e :& es) r)
-> (h e -> Eff e r) -> h e -> Eff (e :& es) r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. h e -> Eff e r
forall (e :: Effects). h e -> Eff e r
k)))

instance (Handle h) => Functor (DslBuilder h) where
  fmap :: forall a b. (a -> b) -> DslBuilder h a -> DslBuilder h b
fmap a -> b
f DslBuilder h a
g = (forall (e :: Effects). h e -> Eff e b) -> DslBuilder h b
forall (h :: Effects -> *) r.
(forall (e :: Effects). h e -> Eff e r) -> DslBuilder h r
dslBuilder (\h e
h -> (a -> b) -> Eff e a -> Eff e b
forall a b. (a -> b) -> Eff e a -> Eff e b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f (h e -> DslBuilder h a -> Eff e a
forall (h :: Effects -> *) (es :: Effects) r.
Handle h =>
h es -> DslBuilder h r -> Eff es r
runDslBuilder h e
h DslBuilder h a
g))

instance (Handle h) => Applicative (DslBuilder h) where
  pure :: forall a. a -> DslBuilder h a
pure a
x = (forall (e :: Effects). h e -> Eff e a) -> DslBuilder h a
forall (h :: Effects -> *) r.
(forall (e :: Effects). h e -> Eff e r) -> DslBuilder h r
dslBuilder (Eff e a -> h e -> Eff e a
forall a. a -> h e -> a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (a -> Eff e a
forall a. a -> Eff e a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
x))
  DslBuilder h (a -> b)
f <*> :: forall a b.
DslBuilder h (a -> b) -> DslBuilder h a -> DslBuilder h b
<*> DslBuilder h a
x = (forall (e :: Effects). h e -> Eff e b) -> DslBuilder h b
forall (h :: Effects -> *) r.
(forall (e :: Effects). h e -> Eff e r) -> DslBuilder h r
dslBuilder (\h e
h -> h e -> DslBuilder h (a -> b) -> Eff e (a -> b)
forall (h :: Effects -> *) (es :: Effects) r.
Handle h =>
h es -> DslBuilder h r -> Eff es r
runDslBuilder h e
h DslBuilder h (a -> b)
f Eff e (a -> b) -> Eff e a -> Eff e b
forall a b. Eff e (a -> b) -> Eff e a -> Eff e b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> h e -> DslBuilder h a -> Eff e a
forall (h :: Effects -> *) (es :: Effects) r.
Handle h =>
h es -> DslBuilder h r -> Eff es r
runDslBuilder h e
h DslBuilder h a
x)

instance (Handle h) => Monad (DslBuilder h) where
  DslBuilder h a
m >>= :: forall a b.
DslBuilder h a -> (a -> DslBuilder h b) -> DslBuilder h b
>>= a -> DslBuilder h b
f = (forall (e :: Effects). h e -> Eff e b) -> DslBuilder h b
forall (h :: Effects -> *) r.
(forall (e :: Effects). h e -> Eff e r) -> DslBuilder h r
dslBuilder ((forall (e :: Effects). h e -> Eff e b) -> DslBuilder h b)
-> (forall (e :: Effects). h e -> Eff e b) -> DslBuilder h b
forall a b. (a -> b) -> a -> b
$ \h e
h -> do
    a
r <- h e -> DslBuilder h a -> Eff e a
forall (h :: Effects -> *) (es :: Effects) r.
Handle h =>
h es -> DslBuilder h r -> Eff es r
runDslBuilder h e
h DslBuilder h a
m
    h e -> DslBuilder h b -> Eff e b
forall (h :: Effects -> *) (es :: Effects) r.
Handle h =>
h es -> DslBuilder h r -> Eff es r
runDslBuilder h e
h (a -> DslBuilder h b
f a
r)