packages feed

zwirn-0.2.2.1: src/zwirn-core/Zwirn/Core/Lib/Core.hs

{-# OPTIONS_GHC -Wno-orphans #-}

module Zwirn.Core.Lib.Core where

{-
    Core.hs - core functions and instances
    Copyright (C) 2025, Martin Gius

    This library is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this library.  If not, see <http://www.gnu.org/licenses/>.
-}

import Control.Monad (join)
import Zwirn.Core.Core as C
import Zwirn.Core.Query
import Zwirn.Core.Time
import Zwirn.Core.Types

-- | indicates the current time
now :: (Applicative k) => ZwirnT k st i Time
now = C.now

-- | indicates the current cycle
cyc :: (Applicative k) => ZwirnT k st i Int
cyc = fmap floor C.now

trig :: (Functor k) => ZwirnT k st i a -> ZwirnT k st i Bool
trig = withValue (\(Value _ t i) -> Value (breakpointCondition 0.005 t) t i)

setInnerTime :: (Applicative k) => ZwirnT k st i Double -> ZwirnT k st i a -> ZwirnT k st i a
setInnerTime = withInner2 (liftA2 (\(vt, _) (va, st) -> (va {time = Time (realToFrac $ value vt) 1}, st)))

getInnerTime :: (Functor k) => ZwirnT k st i a -> ZwirnT k st i Double
getInnerTime = withValue (\v -> v {value = realToFrac $ tTime $ time v})

getSpeed :: (Functor k) => ZwirnT k st i a -> ZwirnT k st i Double
getSpeed = withValue (\v -> v {value = realToFrac $ tDiff $ time v})

apply :: (MultiMonad k) => ZwirnT k st i (ZwirnT k st i a -> ZwirnT k st i b) -> ZwirnT k st i a -> ZwirnT k st i b
apply = zipSqueezeApply

outerApply :: (MultiMonad m) => m (m a -> m b) -> m a -> m b
outerApply f x = outerJoin $ f <*> pure x

innerApply :: (Monad m) => m (m a -> m b) -> m a -> m b
innerApply f x = join $ f <*> pure x

squeezeApply :: (MultiMonad m) => m (m a -> m b) -> m a -> m b
squeezeApply f x = squeezeJoin $ f <*> pure x

zipApply :: (MultiMonad k) => ZwirnT k st i (ZwirnT k st i a -> ZwirnT k st i b) -> ZwirnT k st i a -> ZwirnT k st i b
zipApply fs x = zwirn q
  where
    q t st = innerJoin $ (\c -> unzwirn c t st) . ($ x) . value . fst <$> unzwirn fs t st

zipSqueezeApply :: (MultiMonad k) => ZwirnT k st i (ZwirnT k st i a -> ZwirnT k st i b) -> ZwirnT k st i a -> ZwirnT k st i b
zipSqueezeApply fs x = zwirn q
  where
    q t st = innerJoin $ func <$> unzwirn fs t st
      where
        func f = (\v -> unzwirn (value v x) (time v) st) $ fst f

matchApply :: (MultiMonad k) => ZwirnT k st i (ZwirnT k st i a -> ZwirnT k st i b) -> ZwirnT k st i a -> ZwirnT k st i b
matchApply fs x = innerJoin $ apply fs . pure <$> x

iterate :: (MultiMonad k, HasSilence k) => ZwirnT k st i Int -> ZwirnT k st i (ZwirnT k st i a -> ZwirnT k st i a) -> ZwirnT k st i a -> ZwirnT k st i a
iterate nz fz xz = iterate' =<< nz
  where
    iterate' n = if n < 0 then silence else is !! n
      where
        is = Prelude.iterate (apply fz) xz

squeeze :: (MultiMonad m) => m (m a -> m b) -> m a -> m b
squeeze fp xp = squeezeJoin $ fmap (squeezeApply fp . pure) xp