<commit_before>module Elmz.Signal where

import Elmz.Maybe
import List
import List ((::))
import Maybe
import Result
import Time
import Time (Time)
import Signal (..)

{-| Accumulates into a list using `foldp` during regions where `cond`
    is `True`, otherwise emits the empty list. -}
accumulateWhen : Signal Bool -> Signal a -> Signal (List a)
accumulateWhen cond a = foldpWhen cond (::) [] a |> map List.reverse

{-| Alternate sending `input` through `left` or `right` signal transforms,
    merging their results. -}
alternate : (Signal (Maybe a) -> Signal c)
         -> (Signal (Maybe b) -> Signal c)
         -> Signal (Result a b)
         -> Signal c
alternate left right input =
  let l e = case e of Err e -> Just e
                      Ok _ -> Nothing
      r = Result.toMaybe
      ls = justs (l <~ input)
      rs = justs (r <~ input)
  in merge (left ls) (right rs)

{-| Delay the input `Signal` by one unit. -}
delay : a -> Signal a -> Signal a
delay h s =
  let go a {prev,cur} = { cur = prev, prev = a }
  in foldp go { prev = h, cur = h } s
  |> map .cur

{-| Emit from `t` if `cond` is `True`, otherwise emit from `f`. -}
choose : Signal Bool -> Signal a -> Signal a -> Signal a
choose cond t f =
  let go cond a a2 = if cond then a else a2
  in go <~ cond ~ t ~ f

{-| Spikes `True` for one tick when `a` event fires, otherwise is `False`. -}
changed : Signal a -> Signal Bool
changed a =
  merge (always False <~ Time.delay 0 a)
        (always True <~ a)

{-| Accumulate using `foldp` in between events generated by `reset`. Each `reset`
    event sets the `b` state back to `z`. -}
foldpBetween : Signal r -> (a -> b -> b) -> b -> Signal a -> Signal b
foldpBetween reset f z a =
  let f' a b = case a of
    Nothing -> z
    Just a -> f a b
  in foldp f' z (map (always Nothing) reset `merge` map Just a)

{-| Accumulate using `foldp` in between events generated by `reset`. Each `reset`
    event sets the `b` state back to the current value of `z`. -}
foldpBetween' : Signal r -> (a -> b -> b) -> Signal b -> Signal a -> Signal (Maybe b)
foldpBetween' reset f z a =
  let f' (a,z) b = case b of
    Nothing -> Just (f a z)
    Just b -> Just (f a b)
  in foldpBetween reset f' Nothing (map2 (,) a z)<commit_msg>events combinator<commit_after>module Elmz.Signal where

import Elmz.Maybe
import List
import List ((::))
import Maybe
import Result
import Time
import Time (Time)
import Signal (..)

{-| Accumulates into a list using `foldp` during regions where `cond`
    is `True`, otherwise emits the empty list. -}
accumulateWhen : Signal Bool -> Signal a -> Signal (List a)
accumulateWhen cond a = foldpWhen cond (::) [] a |> map List.reverse

{-| Alternate sending `input` through `left` or `right` signal transforms,
    merging their results. -}
alternate : (Signal (Maybe a) -> Signal c)
         -> (Signal (Maybe b) -> Signal c)
         -> Signal (Result a b)
         -> Signal c
alternate left right input =
  let l e = case e of Err e -> Just e
                      Ok _ -> Nothing
      r = Result.toMaybe
      ls = justs (l <~ input)
      rs = justs (r <~ input)
  in merge (left ls) (right rs)

{-| Delay the input `Signal` by one unit. -}
delay : a -> Signal a -> Signal a
delay h s =
  let go a {prev,cur} = { cur = prev, prev = a }
  in foldp go { prev = h, cur = h } s
  |> map .cur

{-| Emit from `t` if `cond` is `True`, otherwise emit from `f`. -}
choose : Signal Bool -> Signal a -> Signal a -> Signal a
choose cond t f =
  let go cond a a2 = if cond then a else a2
  in go <~ cond ~ t ~ f

{-| Spikes `True` for one tick when `a` event fires, otherwise is `False`. -}
changed : Signal a -> Signal Bool
changed a =
  merge (always False <~ Time.delay 0 a)
        (always True <~ a)

events : Signal a -> Signal (Maybe a)
events s =
  let f b a = if b then Just a else Nothing
  in map2 f (changed s) s

{-| Accumulate using `foldp` in between events generated by `reset`. Each `reset`
    event sets the `b` state back to `z`. -}
foldpBetween : Signal r -> (a -> b -> b) -> b -> Signal a -> Signal b
foldpBetween reset f z a =
  let f' a b = case a of
    Nothing -> z
    Just a -> f a b
  in foldp f' z (map (always Nothing) reset `merge` map Just a)

{-| Accumulate using `foldp` in between events generated by `reset`. Each `reset`
    event sets the `b` state back to the current value of `z`. -}
foldpBetween' : Signal r -> (a -> b -> b) -> Signal b -> Signal a -> Signal (Maybe b)
foldpBetween' reset f z a =
  let f' (a,z) b = case b of
    Nothing -> Just (f a z)
    Just b -> Just (f a b)
  in foldpBetween reset f' Nothing (map2 (,) a z)
{'fraction_non_alphanumeric': 0.12793223284100783, 'fraction_numerical': 0.001954821894005213, 'mean_word_length': 2.528735632183908, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 70, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '773805', 'n_tokens_mistral': 1592, 'n_tokens_neox': 1503, 'n_words': 713}