packages feed

zwirn-core-0.1.1.0: src/Zwirn/Core/Conditional.hs

module Zwirn.Core.Conditional where

{-
    Conditional.hs - conditional functions
    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 Data.Bifunctor (first)
import Data.Fixed (mod')
import Zwirn.Core.Core
import Zwirn.Core.Modulate
import Zwirn.Core.Time
import Zwirn.Core.Types

ifthen :: (MultiMonad k) => ZwirnT k st i Bool -> ZwirnT k st i a -> ZwirnT k st i a -> ZwirnT k st i a
ifthen bz xz yz = innerJoin $ zwirn q
  where
    q t st = first (fmap f) <$> unzwirn bz t st
      where
        f True = xz
        f False = yz

iff :: (MultiMonad k, HasSilence k) => ZwirnT k st i Bool -> ZwirnT k st i a -> ZwirnT k st i a
iff b x = ifthen b x silence

or :: (Applicative k) => ZwirnT k st i Bool -> ZwirnT k st i Bool -> ZwirnT k st i Bool
or = liftA2 (||)

and :: (Applicative k) => ZwirnT k st i Bool -> ZwirnT k st i Bool -> ZwirnT k st i Bool
and = liftA2 (&&)

not :: (Functor k) => ZwirnT k st i Bool -> ZwirnT k st i Bool
not = fmap Prelude.not

eq :: (Eq a, Applicative k) => ZwirnT k st i a -> ZwirnT k st i a -> ZwirnT k st i Bool
eq = liftA2 (==)

leq :: (Ord a, Applicative k) => ZwirnT k st i a -> ZwirnT k st i a -> ZwirnT k st i Bool
leq = liftA2 (<=)

geq :: (Ord a, Applicative k) => ZwirnT k st i a -> ZwirnT k st i a -> ZwirnT k st i Bool
geq = liftA2 (>=)

le :: (Ord a, Applicative k) => ZwirnT k st i a -> ZwirnT k st i a -> ZwirnT k st i Bool
le = liftA2 (<)

ge :: (Ord a, Applicative k) => ZwirnT k st i a -> ZwirnT k st i a -> ZwirnT k st i Bool
ge = liftA2 (>)

while :: (MultiMonad k) => ZwirnT k st i Bool -> ZwirnT k st i (ZwirnT k st i a -> ZwirnT k st i a) -> ZwirnT k st i a -> ZwirnT k st i a
while b f x = ifthen b (squeezeApply f x) x

-- | the first value controls the period the second the length of applying the function in that period
everyFor :: (Monad k) => ZwirnT k st i Time -> ZwirnT k st i Time -> ZwirnT k st i (ZwirnT k st i a -> ZwirnT k st i a) -> ZwirnT k st i a -> ZwirnT k st i a
everyFor t1 t2 f x = everyFor' <$> t1 <*> t2 <*> f <$$> x
  where
    everyFor' :: (Monad k) => Time -> Time -> (ZwirnT k st i a -> ZwirnT k st i a) -> ZwirnT k st i a -> ZwirnT k st i a
    everyFor' per for f x = zwirn $ \t st -> if mod' t per <= for then unzwirn (f x) t st else unzwirn x t st

-- | applies function every period for one cycle
every :: (Monad k) => ZwirnT k st i Time -> ZwirnT k st i (ZwirnT k st i a -> ZwirnT k st i a) -> ZwirnT k st i a -> ZwirnT k st i a
every x = everyFor x (pure 1)