{-# LANGUAGE BlockArguments      #-}
{-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE OverloadedStrings   #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications    #-}
{-# LANGUAGE ViewPatterns        #-}

module Dovetail.Core.Data.Unfoldable1 where

import Data.Vector (Vector)
import Data.Vector qualified as Vector
import Dovetail
import Dovetail.Evaluate (builtIn)

-- unfoldrArrayImpl
--   :: forall a b
--    . (forall x. Maybe x -> Boolean)
--   -> (forall x. Maybe x -> x)
--   -> (forall x y. Tuple x y -> x)
--   -> (forall x y. Tuple x y -> y)
--   -> (b -> Tuple a (Maybe b))
--   -> b
--   -> Array a
unfoldr1ArrayImpl 
  :: (Value ctx -> Eval ctx Bool)
  -> (Value ctx -> Eval ctx (Value ctx))
  -> (Value ctx -> Eval ctx (Value ctx))
  -> (Value ctx -> Eval ctx (Value ctx))
  -> (Value ctx -> Eval ctx (Value ctx)) 
  -> Value ctx 
  -> Eval ctx (Vector (Value ctx))
unfoldr1ArrayImpl :: (Value ctx -> Eval ctx Bool)
-> (Value ctx -> Eval ctx (Value ctx))
-> (Value ctx -> Eval ctx (Value ctx))
-> (Value ctx -> Eval ctx (Value ctx))
-> (Value ctx -> Eval ctx (Value ctx))
-> Value ctx
-> Eval ctx (Vector (Value ctx))
unfoldr1ArrayImpl Value ctx -> Eval ctx Bool
_isNothing Value ctx -> Eval ctx (Value ctx)
_fromJust Value ctx -> Eval ctx (Value ctx)
_fst Value ctx -> Eval ctx (Value ctx)
_snd Value ctx -> Eval ctx (Value ctx)
_f Value ctx
_x = do
  let toMaybe :: Value ctx -> Eval ctx (Maybe (Value ctx))
toMaybe Value ctx
x = Value ctx -> Eval ctx Bool
_isNothing Value ctx
x Eval ctx Bool
-> (Bool -> Eval ctx (Maybe (Value ctx)))
-> Eval ctx (Maybe (Value ctx))
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Bool
b -> if Bool
b then Maybe (Value ctx) -> Eval ctx (Maybe (Value ctx))
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe (Value ctx)
forall a. Maybe a
Nothing else Value ctx -> Maybe (Value ctx)
forall a. a -> Maybe a
Just (Value ctx -> Maybe (Value ctx))
-> Eval ctx (Value ctx) -> Eval ctx (Maybe (Value ctx))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value ctx -> Eval ctx (Value ctx)
_fromJust Value ctx
x
      toTuple :: Value ctx -> Eval ctx (Value ctx, Value ctx)
toTuple Value ctx
x = (,) (Value ctx -> Value ctx -> (Value ctx, Value ctx))
-> Eval ctx (Value ctx)
-> Eval ctx (Value ctx -> (Value ctx, Value ctx))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value ctx -> Eval ctx (Value ctx)
_fst Value ctx
x Eval ctx (Value ctx -> (Value ctx, Value ctx))
-> Eval ctx (Value ctx) -> Eval ctx (Value ctx, Value ctx)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Value ctx -> Eval ctx (Value ctx)
_snd Value ctx
x
  (Value ctx
a, Value ctx
mb) <- Value ctx -> Eval ctx (Value ctx, Value ctx)
toTuple (Value ctx -> Eval ctx (Value ctx, Value ctx))
-> Eval ctx (Value ctx) -> Eval ctx (Value ctx, Value ctx)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Value ctx -> Eval ctx (Value ctx)
_f Value ctx
_x
  Value ctx -> Vector (Value ctx) -> Vector (Value ctx)
forall a. a -> Vector a -> Vector a
Vector.cons Value ctx
a (Vector (Value ctx) -> Vector (Value ctx))
-> Eval ctx (Vector (Value ctx)) -> Eval ctx (Vector (Value ctx))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Value ctx -> Eval ctx (Maybe (Value ctx, Value ctx)))
-> Value ctx -> Eval ctx (Vector (Value ctx))
forall (m :: * -> *) b a.
Monad m =>
(b -> m (Maybe (a, b))) -> b -> m (Vector a)
Vector.unfoldrM (\Value ctx
_mb -> do 
    Maybe (Value ctx)
mb' <- Value ctx -> Eval ctx (Maybe (Value ctx))
toMaybe Value ctx
_mb
    (Value ctx -> Eval ctx (Value ctx, Value ctx))
-> Maybe (Value ctx) -> Eval ctx (Maybe (Value ctx, Value ctx))
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse ((Eval ctx (Value ctx)
-> (Value ctx -> Eval ctx (Value ctx, Value ctx))
-> Eval ctx (Value ctx, Value ctx)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Value ctx -> Eval ctx (Value ctx, Value ctx)
toTuple) (Eval ctx (Value ctx) -> Eval ctx (Value ctx, Value ctx))
-> (Value ctx -> Eval ctx (Value ctx))
-> Value ctx
-> Eval ctx (Value ctx, Value ctx)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Value ctx -> Eval ctx (Value ctx)
_f) Maybe (Value ctx)
mb') Value ctx
mb

env :: forall ctx. Env ctx
env :: Env ctx
env = do
  let _ModuleName :: ModuleName
_ModuleName = Text -> ModuleName
ModuleName Text
"Data.Unfoldable1"

  ModuleName
-> Text
-> ((Value ctx -> Eval ctx Bool)
    -> (Value ctx -> Eval ctx (Value ctx))
    -> (Value ctx -> Eval ctx (Value ctx))
    -> (Value ctx -> Eval ctx (Value ctx))
    -> (Value ctx -> Eval ctx (Value ctx))
    -> Value ctx
    -> Eval ctx (Vector (Value ctx)))
-> Env ctx
forall ctx a. ToValue ctx a => ModuleName -> Text -> a -> Env ctx
builtIn @ctx @_
    ModuleName
_ModuleName Text
"unfoldr1ArrayImpl"
    (Value ctx -> Eval ctx Bool)
-> (Value ctx -> Eval ctx (Value ctx))
-> (Value ctx -> Eval ctx (Value ctx))
-> (Value ctx -> Eval ctx (Value ctx))
-> (Value ctx -> Eval ctx (Value ctx))
-> Value ctx
-> Eval ctx (Vector (Value ctx))
forall ctx.
(Value ctx -> Eval ctx Bool)
-> (Value ctx -> Eval ctx (Value ctx))
-> (Value ctx -> Eval ctx (Value ctx))
-> (Value ctx -> Eval ctx (Value ctx))
-> (Value ctx -> Eval ctx (Value ctx))
-> Value ctx
-> Eval ctx (Vector (Value ctx))
unfoldr1ArrayImpl