packages feed

moffy (empty) → 0.1.0.0

raw patch · 22 files changed

+1516/−0 lines, 22 filesdep +basedep +extra-data-yjdep +freer-par-monadsetup-changed

Dependencies added: base, extra-data-yj, freer-par-monad, moffy, time, type-flip, type-set

Files

+ CHANGELOG.md view
@@ -0,0 +1,11 @@+# Changelog for `moffy`++All notable changes to this project will be documented in this file.++The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),+and this project adheres to the+[Haskell Package Versioning Policy](https://pvp.haskell.org/).++## Unreleased++## 0.1.0.0 - YYYY-MM-DD
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright Yoshikuni Jujo (c) 2023++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Yoshikuni Jujo nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,1 @@+# moffy
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ moffy.cabal view
@@ -0,0 +1,80 @@+cabal-version: 2.2++-- This file has been generated from package.yaml by hpack version 0.35.2.+--+-- see: https://github.com/sol/hpack++name:           moffy+version:        0.1.0.0+synopsis:       Monadic Functional Reactive Programming+description:    Please see the README on GitHub at <https://github.com/YoshikuniJujo/moffy#readme>+category:       Control+homepage:       https://github.com/YoshikuniJujo/moffy#readme+bug-reports:    https://github.com/YoshikuniJujo/moffy/issues+author:         Yoshikuni Jujo+maintainer:     yoshikuni.jujo@gmail.com+copyright:      Copyright (c) 2023 Yoshikuni Jujo+license:        BSD-3-Clause+license-file:   LICENSE+build-type:     Simple+extra-source-files:+    README.md+    CHANGELOG.md++source-repository head+  type: git+  location: https://github.com/YoshikuniJujo/moffy++library+  exposed-modules:+      Control.Moffy+      Control.Moffy.NoThreadId+      Control.Moffy.Internal.React+      Control.Moffy.Internal.React.Type+      Control.Moffy.Internal.Sig+      Control.Moffy.Internal.Sig.Type+      Control.Moffy.Event.Lock+      Control.Moffy.Event.ThreadId+      Control.Moffy.Event.Time+      Control.Moffy.Handle+      Control.Moffy.Handle.Lock+      Control.Moffy.Handle.ThreadId+      Control.Moffy.Handle.Time+      Control.Moffy.Run+  other-modules:+      Control.Moffy.Event.Lock.Internal+      Lib+      Paths_moffy+  autogen-modules:+      Paths_moffy+  hs-source-dirs:+      src+  ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints+  build-depends:+      base >=4.7 && <5+    , extra-data-yj+    , freer-par-monad+    , time+    , type-flip+    , type-set+  default-language: Haskell2010++test-suite moffy-test+  type: exitcode-stdio-1.0+  main-is: Spec.hs+  other-modules:+      Paths_moffy+  autogen-modules:+      Paths_moffy+  hs-source-dirs:+      test+  ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N+  build-depends:+      base >=4.7 && <5+    , extra-data-yj+    , freer-par-monad+    , moffy+    , time+    , type-flip+    , type-set+  default-language: Haskell2010
+ src/Control/Moffy.hs view
@@ -0,0 +1,87 @@+{-# LANGUAGE MonoLocalBinds #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE FlexibleContexts #-}+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}++module Control.Moffy (+	-- * Sig+	Sig, ISig,+	-- * React+	React, Rct, EvReqs, EvOccs, Request(..),+	-- * Constraint+	Firstable, Adjustable,+	-- * Combinator+	-- ** Await and Adjust+	await, adjust, adjustSig, never,+	-- ** Create Sig+	emit, waitFor, repeat,+	-- ** Traverse+	find, scanl,+	-- ** Parallel+	first, at, break, until, indexBy,+	-- ** Copies+	spawn, parList ) where++import Prelude hiding (repeat, scanl, until, break)++import Control.Moffy.Internal.Sig (+	adjustSig, at_, break_, until_, indexBy_, spawn, parList_ )+import Control.Moffy.Internal.Sig.Type (+	Sig, ISig, emit, waitFor, repeat, find, scanl )+import Control.Moffy.Internal.React (Firstable, Adjustable, first_, adjust)+import Control.Moffy.Internal.React.Type (+	React, Rct, EvReqs, EvOccs, Request(..), await, forkThreadId, never )+import Data.Type.Set ((:+:))+import Data.OneOrMore (Mergeable)+import Data.Or (Or)++---------------------------------------------------------------------------++-- * PARALLEL+-- * COPIES++---------------------------------------------------------------------------+-- PARALLEL+---------------------------------------------------------------------------++infixr 8 `first`++first :: Firstable es es' a b =>+	React s es a -> React s es' b -> React s (es :+: es') (Or a b)+first = first_ forkThreadId++infixr 7 `at`++at :: Firstable es es' (ISig s (es :+: es') a r) r' =>+	Sig s es a r -> React s es' r' ->+	React s (es :+: es') (Either r (Maybe a, r'))+at = at_ forkThreadId++infixl 7 `break`, `until`++break :: Firstable es es' (ISig s (es :+: es') a r) r' =>+	Sig s es a r -> React s es' r' ->+	Sig s (es :+: es') a (Either r (Maybe a, r'))+break = break_ forkThreadId++until :: Firstable es es' (ISig s (es :+: es') a r) r' =>+	Sig s es a r -> React s es' r' ->+	Sig s (es :+: es') a (Either r (a, r'))+until = until_ forkThreadId++infixl 7 `indexBy`++indexBy ::+	Firstable es es' (ISig s (es :+: es') a r) (ISig s (es :+: es') b r') =>+	Sig s es a r -> Sig s es' b r' ->+	Sig s (es :+: es') (a, b) (Either r (Maybe a, r'))+indexBy = indexBy_ forkThreadId++---------------------------------------------------------------------------+-- COPIES+---------------------------------------------------------------------------++parList :: ((es :+: es) ~ es, Mergeable es es es) =>+	Sig s es (ISig s es a r) r' -> Sig s es [a] ([r], r')+parList = parList_ forkThreadId
+ src/Control/Moffy/Event/Lock.hs view
@@ -0,0 +1,15 @@+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}++module Control.Moffy.Event.Lock (+	-- * Type+	LockEv, GetThreadIdNewLockId, GetThreadIdGetLock, SingletonUnlock,+	LockId,+	-- * Event Type+	NewLockId, GetLock, Unlock,+	-- * Event+	newLockId, withLock, withLockSig ) where++import Control.Moffy.Event.Lock.Internal (+	LockEv, GetThreadIdNewLockId, GetThreadIdGetLock, SingletonUnlock,+	LockId, newLockId, withLock, withLockSig,+	NewLockId, GetLock, Unlock )
+ src/Control/Moffy/Event/Lock/Internal.hs view
@@ -0,0 +1,110 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE BlockArguments #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE DataKinds, TypeOperators #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE FlexibleContexts #-}+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}++module Control.Moffy.Event.Lock.Internal (+	-- * Type Synonym+	LockEv, GetThreadIdNewLockId, GetThreadIdGetLock, SingletonUnlock,+	-- * Event Type+	NewLockId(..), pattern OccNewLockId, GetLock(..), pattern OccGetLock,+	Unlock(..), pattern OccUnlock, LockId(..),+	-- * Event+	newLockId, withLock, withLockSig ) where++import Control.Moffy (Sig, React, Request(..), Adjustable, adjust, await, waitFor, adjustSig)+import Control.Moffy.Event.ThreadId (GetThreadId, getThreadId, ThreadId)+import Data.Type.Set (numbered, pattern Nil, Singleton, (:-), (:+:))+import Data.OneOrMore (Selectable(..))+import Data.Bool (bool)++---------------------------------------------------------------------------++-- * LOCK ID+-- * EVENT+--	+ NEW LOCK ID+--	+ GET LOCK+--	+ UNLOCK+-- * WITH LOCK++---------------------------------------------------------------------------+-- LOCK ID+---------------------------------------------------------------------------++newtype LockId = LockId Int deriving (Show, Eq)++---------------------------------------------------------------------------+-- EVENT+---------------------------------------------------------------------------++-- NEW LOCK ID++newtype NewLockId = NewLockIdReq ThreadId deriving (Show, Eq)+numbered [t| NewLockId |]+instance Selectable NewLockId where l `select` _r = l+instance Request NewLockId where+	data Occurred NewLockId = OccNewLockId LockId ThreadId++type GetThreadIdNewLockId = GetThreadId :- NewLockId :- 'Nil++newLockId :: React s GetThreadIdNewLockId LockId+newLockId = adjust getThreadId >>= \t -> newLockId `maybe` pure+	=<< (adjust . await (NewLockIdReq t))+		\(OccNewLockId i t') -> bool Nothing (Just i) $ t == t'++-- GET LOCK++data GetLock = GetLockReq LockId ThreadId RetryTime deriving (Show, Eq)+type RetryTime = Int+numbered [t| GetLock |]+instance Selectable GetLock where+	l@(GetLockReq _ _ rtl) `select` r@(GetLockReq _ _ rtr)+		| rtl >= rtr = l | otherwise = r+instance Request GetLock where+	data Occurred GetLock = OccGetLock LockId ThreadId++type GetThreadIdGetLock = GetThreadId :- GetLock :- 'Nil++getLock :: LockId -> RetryTime -> React s GetThreadIdGetLock ()+getLock i rt = adjust getThreadId >>= \t -> getLock i (rt + 1) `bool` pure ()+	=<< (adjust . await (GetLockReq i t rt))+		\(OccGetLock i' t') -> i == i' && t == t'++-- UNLOCK++newtype Unlock = UnlockReq LockId deriving Show+numbered [t| Unlock |]+instance Selectable Unlock where l `select` _r = l+instance Request Unlock where data Occurred Unlock = OccUnlock++type SingletonUnlock = Singleton Unlock++unlock :: LockId -> React s (Singleton Unlock) ()+unlock l = await (UnlockReq l) \OccUnlock -> ()++---------------------------------------------------------------------------+-- WITH LOCK+---------------------------------------------------------------------------++type LockEv = NewLockId :- GetLock :- Unlock :- 'Nil++withLock :: (+	(es :+: es') ~ es',+	(GetThreadIdGetLock :+: es') ~ es', (SingletonUnlock :+: es') ~ es',+	Adjustable es es',+	Adjustable GetThreadIdGetLock es', Adjustable SingletonUnlock es' ) =>+	LockId -> React s es a -> React s es' a+withLock l act = adjust (getLock l 0) >> adjust act <* adjust (unlock l)++withLockSig :: (+	(es :+: es') ~ es',+	(GetThreadIdGetLock :+: es') ~ es', (SingletonUnlock :+: es') ~ es',+	Adjustable es es',+	Adjustable GetThreadIdGetLock es', Adjustable SingletonUnlock es' ) =>+	LockId -> Sig s es a r -> Sig s es' a r+withLockSig l s = do+	waitFor . adjust $ getLock l 0+	adjustSig s <* waitFor (adjust $ unlock l)
+ src/Control/Moffy/Event/ThreadId.hs view
@@ -0,0 +1,24 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE BlockArguments #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}++module Control.Moffy.Event.ThreadId (+	-- * GetThreadId+	GetThreadId, pattern OccGetThreadId, getThreadId,+	-- * ThreadId+	ThreadId ) where++import Control.Moffy.Internal.React.Type (React, Request(..), ThreadId, await')+import Data.Type.Set (numbered, Singleton)++---------------------------------------------------------------------------++data GetThreadId = GetThreadIdReq deriving (Show, Eq, Ord)+numbered [t| GetThreadId |]+instance Request GetThreadId where data Occurred GetThreadId = OccGetThreadId++getThreadId :: React s (Singleton GetThreadId) ThreadId+getThreadId = await' GetThreadIdReq \t OccGetThreadId -> t
+ src/Control/Moffy/Event/Time.hs view
@@ -0,0 +1,65 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE BlockArguments #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE DataKinds, TypeOperators #-}+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}++module Control.Moffy.Event.Time (+	-- * Time Event+	TimeEv,+	-- * Elapsed+	DeltaTime(..), pattern OccDeltaTime, deltaTime, elapsed,+	-- * Sleep+	TryWait(..), pattern OccTryWait, sleep ) where++import Prelude hiding (repeat, scanl)++import GHC.Stack (HasCallStack)+import Control.Moffy (Sig, React, Request(..), await, repeat, scanl)+import Data.Type.Set (numbered, pattern Nil, Singleton, (:-))+import Data.Bool (bool)+import Data.Time (DiffTime)++---------------------------------------------------------------------------++-- * ELAPSED+-- * SLEEP+-- * TIME EVENT++---------------------------------------------------------------------------++---------------------------------------------------------------------------+-- ELAPSED+---------------------------------------------------------------------------++data DeltaTime = DeltaTimeReq deriving (Show, Eq, Ord)+numbered [t| DeltaTime |]+instance Request DeltaTime where data Occurred DeltaTime = OccDeltaTime DiffTime++deltaTime :: React s (Singleton DeltaTime) DiffTime+deltaTime = await DeltaTimeReq \(OccDeltaTime t) -> t++elapsed :: Sig s (Singleton DeltaTime) DiffTime r+elapsed = scanl (+) 0 $ repeat deltaTime++---------------------------------------------------------------------------+-- SLEEP+---------------------------------------------------------------------------++newtype TryWait = TryWaitReq DiffTime deriving (Show, Eq, Ord)+numbered [t| TryWait |]+instance Request TryWait where data Occurred TryWait = OccTryWait DiffTime++tryWait :: DiffTime -> React s (Singleton TryWait) DiffTime+tryWait t = await (TryWaitReq t) \(OccTryWait t') -> t'++sleep :: HasCallStack => DiffTime -> React s (Singleton TryWait) ()+sleep t | t <= 0 = error "sleep t: t (seconds) should be positive"+sleep t = tryWait t >>= \t' -> bool (sleep (t - t')) (pure ()) (t' == t)++---------------------------------------------------------------------------+-- TIME EVENT+---------------------------------------------------------------------------++type TimeEv = DeltaTime :- TryWait :- 'Nil
+ src/Control/Moffy/Handle.hs view
@@ -0,0 +1,179 @@+{-# LANGUAGE LambdaCase, TupleSections #-}+{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE TypeOperators, ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}++module Control.Moffy.Handle (+	-- * Constraint+	ExpandableHandle, ExpandableOccurred, MergeableOccurred,+	-- * Plain Handle+	-- ** Type+	Handle, Handle',+	-- ** Composer+	retry, sleep, sleepIfNothing, expand, before, merge,+	-- * Handle with State+	-- ** Type+	HandleSt, HandleSt', St, liftHandle, liftHandle', liftSt,+	-- ** Composer+	retrySt, expandSt, beforeSt, mergeSt,+	-- * Handle with Input and Output+	-- ** Type+	HandleIo', pushInput, popInput,+	-- ** Composer+	expandIo, beforeIo, mergeIo ) where++import Control.Arrow (first)+import Control.Moffy.Internal.React.Type (+	EvReqs, EvOccs, ExpandableOccurred, MergeableOccurred,+	Handle, HandleSt, St, liftHandle, liftSt )+import Control.Concurrent (threadDelay)+import Data.Type.Set ((:+:))+import Data.OneOrMore (Collapsable)+import Data.OneOrMoreApp (merge')++import qualified Data.OneOrMore as OOM (collapse)+import qualified Data.OneOrMoreApp as OOM (expand)++---------------------------------------------------------------------------++-- * CONSTRAINT+-- * PLAIN HANDLE+--	+ TYPE+--	+ COMPOSER+-- * HANDLE WITH STATE+--	+ TYPE+--	+ COMPOSER+-- * HANDLE WITH INPUT AND OUTPUT+--	+ TYPE+--	+ COMPOSER++---------------------------------------------------------------------------+-- CONSTRAINT+---------------------------------------------------------------------------++type ExpandableHandle es es' = (ExpandableOccurred es es', Collapsable es' es)++---------------------------------------------------------------------------+-- PLAIN HANDLE+---------------------------------------------------------------------------++-- TYPE++type Handle' m es = EvReqs es -> m (Maybe (EvOccs es))++-- COMPOSER++retry :: Monad m => Handle' m es -> Handle m es+retry hdl rqs = retry hdl rqs `maybe` pure =<< hdl rqs++sleep :: Int -> Handle' IO es -> Handle' IO es+sleep n hdl rqs = hdl rqs <* threadDelay n++sleepIfNothing :: Int -> Handle' IO es -> Handle' IO es+sleepIfNothing n hdl rqs = hdl rqs >>= \case+	Nothing -> Nothing <$ threadDelay n+	Just x -> pure $ Just x++collapse :: (Applicative m, Collapsable es' es) =>+	Handle' m es -> EvReqs es' -> m (Maybe (EvOccs es))+collapse hdl = (pure Nothing `maybe` hdl) . OOM.collapse++expand :: (Applicative m, ExpandableHandle es es') =>+	Handle' m es -> Handle' m es'+expand hdl = ((OOM.expand <$>) <$>) . collapse hdl++infixr 5 `before`, `beforeSt`++before :: (+	Monad m,+	ExpandableHandle es (es :+: es'), ExpandableHandle es' (es :+: es') ) =>+	Handle' m es -> Handle' m es' -> Handle' m (es :+: es')+((expand -> l) `before` (expand -> r)) rqs =+	r rqs `maybe` (pure . Just) =<< l rqs++infixr 6 `merge`, `mergeSt`++merge :: (+	Applicative m,+	ExpandableHandle es (es :+: es'), ExpandableHandle es' (es :+: es'),+	MergeableOccurred es es' (es :+: es') ) =>+	Handle' m es -> Handle' m es' -> Handle' m (es :+: es')+((collapse -> l) `merge` (collapse -> r)) rqs = merge' <$> l rqs <*> r rqs++---------------------------------------------------------------------------+-- HANDLE WITH STATE+---------------------------------------------------------------------------++-- TYPE++type HandleSt' st m es = EvReqs es -> St st m (Maybe (EvOccs es))+-- ^ > type HandleSt' st m es = HandleIo' st st m es++liftHandle' :: Functor m => Handle' m es -> HandleSt' st m es+liftHandle' = (liftSt .)++-- COMPOSER++retrySt :: Monad m => HandleSt' st m es -> HandleSt st m es+retrySt hdl rqs st = hdl rqs st >>= \(mo, st') ->+	(retrySt hdl rqs st' `maybe` (pure . (, st'))) mo++expandSt :: (Applicative m, ExpandableHandle es es') =>+	HandleSt' st m es -> HandleSt' st m es'+expandSt = (`expandIo` pure)++beforeSt :: (+	Monad m,+	ExpandableHandle es (es :+: es'), ExpandableHandle es' (es :+: es') ) =>+	HandleSt' st m es -> HandleSt' st m es' -> HandleSt' st m (es :+: es')+l `beforeSt` r = beforeIo l pure r pure++mergeSt :: (+	Monad m,+	ExpandableHandle es (es :+: es'), ExpandableHandle es' (es :+: es'),+	MergeableOccurred es es' (es :+: es') ) =>+	HandleSt' st m es -> HandleSt' st m es' -> HandleSt' st m (es :+: es')+l `mergeSt` r = mergeIo l pure r pure++---------------------------------------------------------------------------+-- HANDLE WITH INPUT AND OUTPUT+---------------------------------------------------------------------------++-- TYPE++type HandleIo' i o m es = EvReqs es -> i -> m (Maybe (EvOccs es), o)++pushInput :: (a -> HandleSt' st m es) -> HandleIo' (a, st) st m es+pushInput = (uncurry .) . flip++popInput :: HandleIo' (a, st) st m es -> a -> HandleSt' st m es+popInput = flip . (curry .)++-- COMPOSER++collapseIo :: (Applicative m, Collapsable es' es) =>+	HandleIo' i o m es -> (i -> m o) ->+	EvReqs es' -> i -> m (Maybe (EvOccs es), o)+collapseIo hdl nh = ((((Nothing ,) <$>) . nh) `maybe` hdl) . OOM.collapse++expandIo :: (Applicative m, ExpandableHandle es es') =>+	HandleIo' i o m es -> (i -> m o) -> HandleIo' i o m es'+expandIo hdl nh rqs = (first (OOM.expand <$>) <$>) . collapseIo hdl nh rqs++beforeIo :: (+	Monad m,+	ExpandableHandle es (es :+: es'), ExpandableHandle es' (es :+: es') ) =>+	HandleIo' i x m es -> (i -> m x) ->+	HandleIo' x o m es' -> (x -> m o) -> HandleIo' i o m (es :+: es')+beforeIo l nhl r nhr rqs st = expandIo l nhl rqs st >>= \(mo, st') ->+	(expandIo r nhr rqs st' `maybe` ((<$> nhr st') . (,) . Just)) mo++mergeIo :: (+	Monad m,+	ExpandableHandle es (es :+: es'), ExpandableHandle es' (es :+: es'),+	MergeableOccurred es es' (es :+: es') ) =>+	HandleIo' i x m es -> (i -> m x) ->+	HandleIo' x o m es' -> (x -> m o) -> HandleIo' i o m (es :+: es')+mergeIo l nhl r nhr rqs st = collapseIo l nhl rqs st >>= \(mo, st') ->+	first (mo `merge'`) <$> collapseIo r nhr rqs st'
+ src/Control/Moffy/Handle/Lock.hs view
@@ -0,0 +1,56 @@+{-# LANGUAGE PatternSynonyms #-}+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}++module Control.Moffy.Handle.Lock (+	-- * Type+	LockEv, LockState(..), LockId,+	-- * Handle+	handleLock ) where++import Control.Moffy.Event.Lock.Internal (+	LockEv, LockId(..), NewLockId(..), pattern OccNewLockId,+	GetLock(..), pattern OccGetLock, Unlock(..), pattern OccUnlock )+import Control.Moffy.Handle (HandleSt', mergeSt)+import Data.Type.Set (Singleton)+import Data.OneOrMore as Oom (pattern Singleton)+import Data.Bool (bool)++import Data.OneOrMoreApp as Ooma (pattern Singleton)++---------------------------------------------------------------------------++-- * LOCK STATE+-- * HANDLE++---------------------------------------------------------------------------+-- LOCK STATE+---------------------------------------------------------------------------++class LockState s where+	getNextLockId :: s -> Int; putNextLockId :: s -> Int -> s+	isLocked :: s -> LockId -> Bool+	lockIt :: s -> LockId -> s; unlockIt :: s -> LockId -> s++---------------------------------------------------------------------------+-- HANDLE+---------------------------------------------------------------------------++handleLock :: (LockState s, Monad m) => HandleSt' s m LockEv+handleLock = handleNewLockId `mergeSt` handleGetLock `mergeSt` handleUnlock++handleNewLockId ::+	(LockState s, Applicative m) => HandleSt' s m (Singleton NewLockId)+handleNewLockId (Oom.Singleton (NewLockIdReq t)) s = pure (+	Just . Ooma.Singleton $ OccNewLockId (LockId i) t,+	s `putNextLockId` (i + 1) )+	where i = getNextLockId s++handleGetLock ::+	(LockState s, Applicative m) => HandleSt' s m (Singleton GetLock)+handleGetLock (Oom.Singleton (GetLockReq i t _)) s = pure $ bool+	(Just . Ooma.Singleton $ OccGetLock i t, s `lockIt` i) (Nothing, s)+	(s `isLocked` i)++handleUnlock :: (LockState s, Applicative m) => HandleSt' s m (Singleton Unlock)+handleUnlock (Oom.Singleton (UnlockReq i)) s =+	pure (Just $ Ooma.Singleton OccUnlock, s `unlockIt` i)
+ src/Control/Moffy/Handle/ThreadId.hs view
@@ -0,0 +1,19 @@+{-# LANGUAGE PatternSynonyms #-}+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}++module Control.Moffy.Handle.ThreadId (+	-- * GetThreadId+	GetThreadId,+	-- * Handle+	handleGetThreadId ) where++import Control.Moffy.Event.ThreadId (GetThreadId, pattern OccGetThreadId)+import Control.Moffy.Handle (Handle')+import Data.Type.Set (Singleton)++import Data.OneOrMoreApp++---------------------------------------------------------------------------++handleGetThreadId :: Applicative m => Handle' m (Singleton GetThreadId)+handleGetThreadId _rqs = pure . Just $ Singleton OccGetThreadId
+ src/Control/Moffy/Handle/Time.hs view
@@ -0,0 +1,110 @@+{-# LANGUAGE LambdaCase, TupleSections #-}+{-# LANGUAGE PatternSynonyms, ConstraintKinds #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE FlexibleContexts, FlexibleInstances #-}+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}++module Control.Moffy.Handle.Time (+	-- * TimeState+	TimeState(..), Mode(InitialMode),+	-- * IO Mimicable+	TaiTimeM(..), DelayM(..),+	-- * Handle+	Timable, handleTimeEvPlus ) where++import Control.Arrow (first, second, (>>>))+import Control.Moffy.Event.Time (+	TimeEv, pattern OccDeltaTime, TryWait(..), pattern OccTryWait )+import Control.Moffy.Handle (+	ExpandableHandle, MergeableOccurred, HandleIo', expandIo, mergeIo )+import Control.Concurrent (threadDelay)+import Data.Type.Set ((:+:))+import Data.OneOrMore (project)+import Data.Time (DiffTime)+import Data.Time.Clock.TAI (AbsoluteTime, diffAbsoluteTime, addAbsoluteTime)+import Data.Time.Clock.System (getSystemTime, systemToTAITime)++import Data.OneOrMoreApp (expand, pattern Singleton, (>-))+	+---------------------------------------------------------------------------++-- * TIME STATE+-- * IO MIMICABLE+-- * HANDLE++---------------------------------------------------------------------------++---------------------------------------------------------------------------+-- TIME STATE+---------------------------------------------------------------------------++class TimeState s where+	getMode :: s -> Mode; putMode :: s -> Mode -> s+	getLatestTime :: s -> AbsoluteTime+	putLatestTime :: s -> AbsoluteTime -> s++instance TimeState (Mode, AbsoluteTime) where+	getMode = fst; putMode s = flip first s . const+	getLatestTime = snd; putLatestTime s = flip second s . const++updateTimeState :: TimeState s => s -> (Mode, AbsoluteTime) -> s+updateTimeState s (m, t) = s `putMode` m `putLatestTime` t++data Mode = InitialMode | FlushWaitMode AbsoluteTime deriving Show++mode :: a -> (AbsoluteTime -> a) -> Mode -> a+mode im fwm = \case InitialMode -> im; FlushWaitMode t -> fwm t++---------------------------------------------------------------------------+-- IO MIMICABLE+---------------------------------------------------------------------------++class TaiTimeM m where getCurrentTime :: m AbsoluteTime+instance TaiTimeM IO where getCurrentTime = systemToTAITime <$> getSystemTime++class DelayM m where delay :: DiffTime -> m ()+instance DelayM IO where delay = threadDelay . round . (* 10 ^ (6 :: Int))++---------------------------------------------------------------------------+-- HANDLE+---------------------------------------------------------------------------++type Timable es = (+	ExpandableHandle es (es :+: TimeEv),+	ExpandableHandle TimeEv (es :+: TimeEv),+	MergeableOccurred es TimeEv (es :+: TimeEv) )++handleTimeEvPlus :: (TimeState s, Monad m, TaiTimeM m, DelayM m, Timable es) =>+	HandleIo' ((DiffTime, a), s) s m es ->+	HandleIo' ((DiffTime, a), s) s m (es :+: TimeEv)+handleTimeEvPlus hdl rqs i@(_, s) = ($ s) $ getMode+	>>> mode (handleI hdl rqs i) (handleF rqs . (, s) . (, getLatestTime s))++handleI :: (TimeState s, Monad m, TaiTimeM m, DelayM m, Timable es) =>+	HandleIo' ((DiffTime, a), s) s m es ->+	HandleIo' ((DiffTime, a), s) s m (es :+: TimeEv)+handleI hdl = mergeIo+	hdl (\((d, _), s) -> s <$ delay d)+	(\rqs s -> (updateTimeState s `second`)+		<$> (handleTime rqs . (, getLatestTime s) =<< getCurrentTime))+	((<$> getCurrentTime) . putLatestTime)++handleF :: (TimeState s, Monad m, ExpandableHandle TimeEv es) =>+	HandleIo' ((AbsoluteTime, AbsoluteTime), s) s m es+handleF rqs (nl, s) = (updateTimeState s `second`)+	<$> expandIo handleTime (pure . (InitialMode ,) . fst) rqs nl++handleTime :: Monad m =>+	HandleIo' (AbsoluteTime, AbsoluteTime) (Mode, AbsoluteTime) m TimeEv+handleTime rqs (now, lst) = case project rqs of+	Just (TryWaitReq t)+		| t < dt  -> pure (+			Just $ OccTryWait t >- Singleton (OccDeltaTime t),+			(FlushWaitMode now, t `addAbsoluteTime` lst) )+		| otherwise -> pure (+			Just $ OccTryWait dt >- Singleton (OccDeltaTime dt),+			(InitialMode, now) )+	Nothing -> pure (+		Just . expand . Singleton $ OccDeltaTime dt,+		(InitialMode, now) )+	where dt = now `diffAbsoluteTime` lst
+ src/Control/Moffy/Internal/React.hs view
@@ -0,0 +1,114 @@+{-# LANGUAGE BlockArguments, LambdaCase, TupleSections #-}+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}+{-# LANGUAGE TypeOperators, ConstraintKinds #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE MultiParamTypeClasses, FlexibleContexts, FlexibleInstances,+	UndecidableInstances #-}+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}++module Control.Moffy.Internal.React (+	-- * Class+	Adjustable, Updatable,+	-- * Constraint Synonym+	Firstable,+	-- * Function+	adjust, first_, par) where++import Control.Arrow ((***))+import Control.Monad.Freer.Par (+	pattern Pure, pattern (:=<<), (=<<<), app, appPar )+import Control.Moffy.Internal.React.Type (+	React, Rct(..), EvOccs, CollapsableOccurred, ThreadId, never )+import Data.Type.Set ((:+:))+import Data.OneOrMore (Expandable, Mergeable, expand, merge)+import Data.Or (Or(..))++import Data.OneOrMoreApp (collapse)++---------------------------------------------------------------------------++-- * FIRST+-- * ADJUST+-- * PAR+-- * UPDATABLE++---------------------------------------------------------------------------+-- FIRST+---------------------------------------------------------------------------++type Firstable es es' a b = (+	Updatable a b, Adjustable es (es :+: es'), Adjustable es' (es :+: es'),+	((es :+: es') :+: (es :+: es')) ~ (es :+: es'),+	Mergeable (es :+: es') (es :+: es') (es :+: es') )++first_ :: Firstable es es' a b =>+	React s (es :+: es') (ThreadId, ThreadId) ->+	React s es a -> React s es' b -> React s (es :+: es') (Or a b)+first_ ft (adjust -> l) (adjust -> r) = (<$> par ft l r) \case+	(Pure x, Pure y) -> LR x y; (Pure x, _) -> L x; (_, Pure y) -> R y+	(_ :=<< _, _:=<< _) -> error "never occur"++---------------------------------------------------------------------------+-- ADJUST+---------------------------------------------------------------------------++class Adjustable es es' where adjust :: React s es a -> React s es' a+instance Adjustable es es where adjust = id+instance {-# OVERLAPPABLE #-} (Expandable es es', CollapsableOccurred es' es) =>+	Adjustable es es' where adjust = adj++adj :: (Expandable es es', CollapsableOccurred es' es) =>+	React s es a -> React s es' a+adj = \case+	Pure x -> pure x; _ :=<< Never -> never+	c :=<< GetThreadId -> adj . (c `app`) =<<< GetThreadId+	r@(c :=<< Await e) ->+		adj . maybe r (c `app`) . collapse =<<< Await (expand e)++---------------------------------------------------------------------------+-- PAR+---------------------------------------------------------------------------++par :: (Updatable a b, Mergeable es es es, (es :+: es) ~ es) =>+	React s es (ThreadId, ThreadId) ->+	React s es a -> React s es b -> React s es (React s es a, React s es b)+par ft l r = case (l, r) of+	(Pure _, _) -> pure (l, r); (_, Pure _) -> pure (l, r)+	(_ :=<< Never, _ :=<< Never) -> never+	(_ :=<< Never, _) -> (never ,) . pure <$> r+	(_, _ :=<< Never) -> (, never) . pure <$> l+	(c :=<< GetThreadId, c' :=<< GetThreadId) ->+		uncurry (par ft) . (app c *** app c') =<< ft+	(c :=<< GetThreadId, _) -> flip (par ft) r . app c . fst =<< ft+	(_, c' :=<< GetThreadId) -> par ft l . app c' . snd =<< ft+	(_ :=<< Await el, _ :=<< Await er) -> ft >>= \(t, u) ->+		uncurry (par ft)+			. update l t r u =<< pure =<<< Await (el `merge` er)++---------------------------------------------------------------------------+-- UPDATABLE+---------------------------------------------------------------------------++class Updatable a b where+	update :: React s es a -> ThreadId -> React s es b -> ThreadId ->+		EvOccs es -> (React s es a, React s es b)++instance Updatable a a where+	update (c :=<< GetThreadId) t (c' :=<< GetThreadId) u x =+		update (c `app` t) t (c' `app` u) u x+	update (c :=<< GetThreadId) t r u x = update (c `app` t) t r u x+	update l t (c' :=<< GetThreadId) u x = update l t (c' `app` u) u x+	update l@(_ :=<< Never) _ (c' :=<< Await _) _ x = (l, c' `app` x)+	update (c :=<< Await _) _ r@(_ :=<< Never) _ x = (c `app` x, r)+	update (c :=<< Await _) _ (c' :=<< Await _) _ x = appPar c c' x+	update l _ r _ _ = (l, r)++instance {-# OVERLAPPABLE #-} Updatable a b where+	update (c :=<< GetThreadId) t (c' :=<< GetThreadId) u x =+		update (c `app` t) t (c' `app` u) u x+	update (c :=<< GetThreadId) t r u x = update (c `app` t) t r u x+	update l t (c' :=<< GetThreadId) u x = update l t (c' `app` u) u x+	update l@(_ :=<< Never) _ (c' :=<< Await _) _ x = (l, c' `app` x)+	update (c :=<< Await _) _ r@(_ :=<< Never) _ x = (c `app` x, r)+	update (c :=<< Await _) _ (c' :=<< Await _) _ x = (c `app` x, c' `app` x)+	update l _ r _ _ = (l, r)
+ src/Control/Moffy/Internal/React/Type.hs view
@@ -0,0 +1,110 @@+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE DataKinds, TypeOperators, ConstraintKinds #-}+{-# LANGUAGE GADTs, TypeFamilies #-}+{-# LANGUAGE FlexibleContexts #-}+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}++module Control.Moffy.Internal.React.Type (+	-- * React+	-- ** Type React and Data Rct+	React, Rct(..), EvReqs, EvOccs,+	-- ** Class Request+	Request(..),+	-- ** Constraint Synonym for Data Occurred+	ExpandableOccurred, CollapsableOccurred, MergeableOccurred,+	-- * Never and Await+	never, await, await',+	-- * Handle+	Handle, HandleSt, St, liftHandle, liftSt,+	-- * ThreadId+	ThreadId, rootThreadId, noThreadId, forkThreadId ) where++import Control.Monad.Freer.Par (Freer, (=<<<), (>>>=))+import Control.Monad.Freer.Par.FTCQueue (FTCQueue)+import Control.Monad.Freer.Par.TaggableFunction (TaggableFun)+import Data.Kind (Type)+import Data.Type.Set (Set, Numbered, Singleton)+import Data.OneOrMore (OneOrMore, Selectable, pattern Singleton)+import Data.Bits (setBit)+import Numeric.Natural (Natural)++import Data.Type.SetApp+import Data.OneOrMoreApp (+	OneOrMoreApp, Expandable, Collapsable, Mergeable, unSingleton )++---------------------------------------------------------------------------++-- * REACT+--	+ TYPE+--	+ NEVER AND AWAIT+-- * CONSTRAINT SYNONYM+-- * HANDLE+-- * THREAD ID++---------------------------------------------------------------------------+-- REACT+---------------------------------------------------------------------------++-- TYPE++type React s es = Freer s FTCQueue TaggableFun (Rct es)++data Rct es r where+	Never :: Rct es r; GetThreadId :: Rct es ThreadId+	Await :: EvReqs es -> Rct es (EvOccs es)++class (Numbered e, Selectable e) => Request e where data Occurred e++type EvReqs (es :: Set Type) = OneOrMore es+type EvOccs (es :: Set Type) = OneOrMoreApp (Occurred :$: es)++-- NEVER AND AWAIT++never :: React s es a+never = pure =<<< Never++await :: e -> (Occurred e -> r) -> React s (Singleton e) r+await rq f = pure . f . unSingleton =<<< Await (Singleton rq)++await' :: e -> (ThreadId -> Occurred e -> r) -> React s (Singleton e) r+await' rq f = await rq . f =<<< GetThreadId++---------------------------------------------------------------------------+-- CONSTRAINT SYNONYM+---------------------------------------------------------------------------++type ExpandableOccurred es es' = Expandable Occurred es es'++type CollapsableOccurred es es' = Collapsable Occurred es es'++type MergeableOccurred es es' mrg = Mergeable Occurred es es' mrg++---------------------------------------------------------------------------+-- HANDLE+---------------------------------------------------------------------------++type Handle m es = EvReqs es -> m (EvOccs es)+type HandleSt st m es = EvReqs es -> St st m (EvOccs es)+type St st m a = st -> m (a, st)++liftHandle :: Functor m => Handle m es -> HandleSt st m es+liftHandle = (liftSt .)++liftSt :: Functor m => m r -> St st m r+liftSt m = (<$> m) . flip (,)++---------------------------------------------------------------------------+-- THREAD ID+---------------------------------------------------------------------------++data ThreadId = NoThreadId | ThreadId Natural Int deriving (Show, Eq)++rootThreadId :: ThreadId+rootThreadId = ThreadId 0 0++noThreadId :: React s es (ThreadId, ThreadId)+noThreadId = pure (NoThreadId, NoThreadId)++forkThreadId :: React s es (ThreadId, ThreadId)+forkThreadId = GetThreadId >>>= \(ThreadId n i) ->+	pure (ThreadId n $ i + 1, ThreadId (n `setBit` i) $ i + 1)
+ src/Control/Moffy/Internal/Sig.hs view
@@ -0,0 +1,237 @@+{-# LANGUAGE BlockArguments, LambdaCase, TupleSections #-}+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE FlexibleContexts, FlexibleInstances, UndecidableInstances #-}+{-# OPTIONS_GHC -Wall -fno-warn-tabs -fno-warn-orphans #-}++module Control.Moffy.Internal.Sig (+	-- * Adjust+	adjustSig,+	-- * Applicative+	app_, iapp_,+	-- * Parallel+	at_, break_, until_, indexBy_,+	-- * Copies+	spawn, parList_ ) where++import Prelude hiding (repeat)++import Control.Arrow (first, (>>>), (***))+import Control.Monad.Freer.Par (pattern Pure, pattern (:=<<))+import Control.Moffy.Internal.Sig.Type (+	Sig(..), ISig(..), isig,+	emit, emitAll, waitFor, repeat, res, ires, hold )+import Control.Moffy.Internal.React (+	Firstable, Adjustable, Updatable, adjust, par )+import Control.Moffy.Internal.React.Type (+	React, Rct(..), ThreadId, forkThreadId )+import Data.Type.Set ((:+:))+import Data.Type.Flip (Flip(..), (<$%>))+import Data.OneOrMore (Mergeable)++---------------------------------------------------------------------------++-- * FLIP APPLIICATIVE+--	+ INSTANCE APPLICATIVE+--	+ APP AND IAPP+-- * PARALLEL+--	+ AT+--	+ BREAK AND UNTIL+--	+ INDEX BY+-- * COPIES+--	+ SPAWN+--	+ PAR LIST+-- * BASIC COMBINATOR+--	+ ADJUST+--	+ PAIRS+--	+ PAUSE++---------------------------------------------------------------------------+-- FLIP APPLICATIVE+---------------------------------------------------------------------------++-- INSTANCE APPLICATIVE++instance ((es :+: es) ~ es, Mergeable es es es, Monoid r) =>+	Applicative (Flip (Sig s es) r) where+	pure = Flip . Sig . pure . unflip . pure+	mf <*> mx = Flip $ app_ forkThreadId (unflip mf) (unflip mx)++instance ((es :+: es) ~ es, Mergeable es es es, Semigroup r) =>+	Applicative (Flip (ISig s es) r) where+	pure = Flip . (:| hold)+	mf <*> mx = Flip $ iapp_ forkThreadId (unflip mf) (unflip mx)++-- APP AND IAPP++app_ :: ((es :+: es) ~ es, Mergeable es es es, Monoid r) =>+	React s es (ThreadId, ThreadId) ->+	Sig s es (a -> b) r -> Sig s es a r -> Sig s es b r+app_ ft mf mx = emitAll . maybe (pure mempty) (uncurry $ iapp_ ft) =<< waitFor (exposeBoth ft mf mx)++exposeBoth :: (+	Updatable (ISig s es a r) (ISig s es b r'),+	Updatable (ISig s es b r') (ISig s es a r), (es :+: es) ~ es, Mergeable es es es ) =>+	React s es (ThreadId, ThreadId) -> Sig s es a r -> Sig s es b r' ->+	React s es (Maybe (ISig s es a r, ISig s es b r'))+exposeBoth ft l (Sig r) = do+	(Sig l', r') <- res $ pause ft l r+	(Sig r'', l'') <- res $ pause ft (Sig r') l'+	pure $ (,) <$> ex l'' <*> ex r''+	where ex = \case Pure x -> Just x; _ -> Nothing++iapp_ :: ((es :+: es) ~ es, Mergeable es es es, Semigroup r) =>+	React s es (ThreadId, ThreadId) ->+	ISig s es (a -> b) r -> ISig s es a r -> ISig s es b r+iapp_ ft mf mx = (<$> (uncurry ($) <$%> ipairs ft mf mx)) \case+	(End x, End y) -> x <> y; (End x, _ :| _) -> x; (_ :| _, End y) -> y+	(_ :| _, _ :| _) -> error "never occur"++---------------------------------------------------------------------------+-- PARALLEL+---------------------------------------------------------------------------++-- AT++at_ :: Firstable es es' (ISig s (es :+: es') a r) r' =>+	React s (es :+: es') (ThreadId, ThreadId) ->+	Sig s es a r -> React s es' r' ->+	React s (es :+: es') (Either r (Maybe a, r'))+at_ ft (adjustSig -> Sig l) (adjust -> r) = par ft l r >>= \case+	(Pure l', r') -> (first Just <$>) <$> iat_ ft l' r'+	(_, Pure y) -> pure $ Right (Nothing, y)+	(_ :=<< _, _ :=<< _) -> error "never occur"++iat_ :: (Updatable (ISig s es a r) r', (es :+: es) ~ es, Mergeable es es es) =>+	React s es (ThreadId, ThreadId) ->+	ISig s es a r -> React s es r' -> React s es (Either r (a, r'))+iat_ ft l r = (<$> ires (ipause ft l r)) \case+	(End x, _) -> Left x; (h :| _, Pure y) -> Right (h, y)+	(_ :| _, _ :=<< _) -> error "never occur"++-- BREAK AND UNTIL++break_ :: Firstable es es' (ISig s (es :+: es') a r) r' =>+	React s (es :+: es') (ThreadId, ThreadId) ->+	Sig s es a r -> React s es' r' ->+	Sig s (es :+: es') a (Either r (Maybe a, r'))+break_ ft (adjustSig -> l) (adjust -> r) = (<$> pause ft l r)+	$ first unSig >>> \case+		(Pure (End x), _) -> Left x+		(_ :=<< Await _, Pure r') -> Right (Nothing, r')+		(Pure (h :| _), Pure r') -> Right (Just h, r')+		_ -> error "never occur"++until_ :: Firstable es es' (ISig s (es :+: es') a r) r' =>+	React s (es :+: es') (ThreadId, ThreadId) ->+	Sig s es a r -> React s es' r' ->+	Sig s (es :+: es') a (Either r (a, r'))+until_ ft (adjustSig -> l) (adjust -> r) = pause ft l r >>= \(Sig l', r') ->+	(<$> waitFor l') \case+		End x -> Left x+		h :| _ -> case r' of+			Pure y -> Right (h, y); _ -> error "never occur"++-- INDEX BY++indexBy_ ::+	Firstable es es' (ISig s (es :+: es') a r) (ISig s (es :+: es') b r') =>+	React s (es :+: es') (ThreadId, ThreadId) ->+	Sig s es a r -> Sig s es' b r' ->+	Sig s (es :+: es') (a, b) (Either r (Maybe a, r'))+indexBy_ ft (adjustSig -> l) (adjustSig -> r) = indexByGen ft l r++indexByGen ::+	(Updatable (ISig s es a r) (ISig s es b r'), (es :+: es) ~ es, Mergeable es es es) =>+	React s es (ThreadId, ThreadId) ->+	Sig s es a r -> Sig s es b r' -> Sig s es (a, b) (Either r (Maybe a, r'))+indexByGen ft l (Sig r) = waitFor (res $ pause ft l r) >>= \case+	(Sig (Pure l'), r') -> (first Just <$>) <$> iindexBy ft l' (Sig r')+	(l', Pure (_ :| r')) -> indexByGen ft l' r'+	(_, Pure (End y)) -> pure $ Right (Nothing, y)+	_ -> error "never occur"++iindexBy :: (Updatable (ISig s es a r) (ISig s es b r'), (es :+: es) ~ es, Mergeable es es es) =>+	React s es (ThreadId, ThreadId) ->+	ISig s es a r -> Sig s es b r' -> Sig s es (a, b) (Either r (a, r'))+iindexBy ft l (Sig r) = waitFor (ires $ ipause ft l r) >>= \case+	(End x, _) -> pure $ Left x+	(l'@(hl :| _), Pure (x :| r')) -> emit (hl, x) >> iindexBy ft l' r'+	(hl :| _, Pure (End y)) -> pure $ Right (hl, y)+	_ -> error "never occur"++---------------------------------------------------------------------------+-- COPIES+---------------------------------------------------------------------------++-- SPAWN++spawn :: Sig s es a r -> Sig s es (ISig s es a r) r'+spawn = repeat . unSig++-- PAR 	LIST++parList_, parListGen :: ((es :+: es) ~ es, Mergeable es es es) =>+	React s es (ThreadId, ThreadId) ->+	Sig s es (ISig s es a r) r' -> Sig s es [a] ([r], r')+parList_ ft s = reverse <$%> parListGen ft s+parListGen ft (Sig r) = iparList ft =<< waitFor r++iparList :: ((es :+: es) ~ es, Mergeable es es es) =>+	React s es (ThreadId, ThreadId) ->+	ISig s es (ISig s es a r) r' -> Sig s es [a] ([r], r')+iparList ft = isig (pure . ([] ,)) $ go . ((: []) <$>) . ((: []) <$%>) where+	go s (Sig r) = emitAll (ipause ft s r) >>= \case+		(s', Pure (h :| t)) -> go (cons ft h s') t+		(s', Pure (End y)) -> (, y) <$> emitAll s'+		(End x, r') -> emit [] >> first (x ++) <$> parListGen ft (Sig r')+		(_ :| _, _ :=<< _) -> error "never occur"++cons :: ((es :+: es) ~ es, Mergeable es es es) =>+	React s es (ThreadId, ThreadId) ->+	ISig s es a r -> ISig s es [a] [r] -> ISig s es [a] [r]+cons ft h t = uncurry (:) <$%> ipairs ft h t >>= \(h', t') ->+	(:) <$> ((: []) <$%> h') <*> t'++---------------------------------------------------------------------------+-- BASIC COMBINATOR+---------------------------------------------------------------------------++-- ADJUST++adjustSig :: Adjustable es es' => Sig s es a r -> Sig s es' a r+adjustSig = Sig . (adjustISig <$>) . adjust . unSig++adjustISig :: Adjustable es es' => ISig s es a r -> ISig s es' a r+adjustISig = isig End $ (adjustSig >>>) . (:|)++-- PAIRS++ipairs :: (Updatable (ISig s es a r) (ISig s es b r'), Mergeable es es es, (es :+: es) ~ es) =>+	React s es (ThreadId, ThreadId) -> ISig s es a r -> ISig s es b r' ->+	ISig s es (a, b) (ISig s es a r, ISig s es b r')+ipairs _ l@(End _) r = pure (l, r)+ipairs _ l r@(End _) = pure (l, r)+ipairs ft (hl :| Sig tl) (hr :| Sig tr) = ((hl, hr) :|) . Sig+	$ uncurry (ipairs ft) . ((hl ?:|) *** (hr ?:|)) <$> par ft tl tr+	where (?:|) h = \case Pure i -> i; t -> h :| Sig t++-- PAUSE++pause :: (Updatable (ISig s es a r) r', (es :+: es) ~ es, Mergeable es es es) =>+	React s es (ThreadId, ThreadId) -> Sig s es a r -> React s es r' ->+	Sig s es a (Sig s es a r, React s es r')+pause ft (Sig l) r = waitFor (par ft l r) >>= \case+	(Pure l', r') -> first emitAll <$> emitAll (ipause ft l' r')+	(l', r'@(Pure _)) -> pure (Sig l', r')+	_ -> error "never occur"++ipause :: (Updatable (ISig s es a r) r', (es :+: es) ~ es, Mergeable es es es) =>+	React s es (ThreadId, ThreadId) -> ISig s es a r -> React s es r' ->+	ISig s es a (ISig s es a r, React s es r')+ipause _ l@(End _) r = pure (l, r)+ipause ft (h :| t) r = (h :|) $ (<$> pause ft t r) \case+	(Sig (Pure t'), r') -> (t', r')+	(t', r'@(Pure _)) -> (h :| t', r')+	_ -> error "never occur"
+ src/Control/Moffy/Internal/Sig/Type.hs view
@@ -0,0 +1,115 @@+{-# LANGUAGE BlockArguments, LambdaCase #-}+{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE FlexibleInstances #-}+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}++module Control.Moffy.Internal.Sig.Type (+	-- * Type+	Sig(..), ISig(..), isig,+	-- * Function+	-- ** Basic+	emit, emitAll, waitFor, res, ires, hold,+	-- ** Practical+	repeat, find, scanl ) where++import Prelude hiding (repeat, scanl)++import Control.Monad (forever, (<=<))+import Control.Moffy.Internal.React.Type (React, never)+import Data.Type.Flip (Flip(..), (<$%>))+import Data.Bool (bool)++---------------------------------------------------------------------------++-- * TYPE+-- * CLASS INSTANCE+--	+ MONAD+--	+ FLIP FUNCTOR+-- * FUNCTION+--	+ BASIC+--	+ PRACTICAL++---------------------------------------------------------------------------+-- TYPE+---------------------------------------------------------------------------++infixr 5 :|+newtype Sig s es a r = Sig { unSig :: React s es (ISig s es a r) }+data ISig s es a r = End r | a :| Sig s es a r++isig :: (r -> b) -> (a -> Sig s es a r -> b) -> ISig s es a r -> b+isig e c = \case End x -> e x; h :| t -> c h t++---------------------------------------------------------------------------+-- CLASS INSTANCE+---------------------------------------------------------------------------++-- MONAD++instance Functor (Sig s es a) where fmap f = Sig . ((f <$>) <$>) . unSig++instance Applicative (Sig s es a) where+	pure = emitAll . pure; Sig rf <*> (flip (<$>) -> ax) =+		Sig $ isig (unSig . ax) (\h -> pure . (h :|) . (ax =<<)) =<< rf++instance Monad (Sig s es a) where+	Sig r >>= f =+		Sig $ isig (unSig . f) (\h -> pure . (h :|) . (f =<<)) =<< r++instance Functor (ISig s es a) where+	fmap f = isig (End . f) \h -> (h :|) . (f <$>)++instance Applicative (ISig s es a) where+	pure = End; mf <*> (flip (<$>) -> ax) =+		isig ax (\h -> (h :|) . (emitAll . ax =<<)) mf++instance Monad (ISig s es a) where+	m >>= f = isig f (\h -> (h :|) . (emitAll . f =<<)) m++-- FLIP FUNCTOR++instance Functor (Flip (Sig s es) r) where+	fmap f = Flip . Sig . ((f <$%>) <$>) . unSig . unflip++instance Functor (Flip (ISig s es) r) where+	fmap f = Flip . isig pure (\h -> (f h :|) . (f <$%>)) . unflip++---------------------------------------------------------------------------+-- FUNCTION+---------------------------------------------------------------------------++-- BASIC++emit :: a -> Sig s es a ()+emit = emitAll . (:| pure ())++emitAll :: ISig s es a r -> Sig s es a r+emitAll = Sig . pure++waitFor :: React s es r -> Sig s es a r+waitFor = Sig . (pure <$>)++res :: Sig s es a r -> React s es r+res = ires <=< unSig++ires :: ISig s es a r -> React s es r+ires = isig pure $ const res++hold :: Sig s es a r+hold = waitFor never++-- PRACTICAL++repeat :: React s es a -> Sig s es a r+repeat = forever . (emit <=< waitFor)++find :: (a -> Bool) -> Sig s es a r -> React s es (Either a r)+find p = go where+	go = igo <=< unSig+	igo = isig (pure . Right) \h -> bool go (const . pure $ Left h) (p h)++scanl :: (b -> a -> b) -> b -> Sig s es a r -> Sig s es b r+scanl = ((emitAll .) .) . iscanl++iscanl :: (b -> a -> b) -> b -> Sig s es a r -> ISig s es b r+iscanl op v (Sig r) = v :| (isig pure (scanl op . (v `op`)) =<< waitFor r)
+ src/Control/Moffy/NoThreadId.hs view
@@ -0,0 +1,88 @@+{-# LANGUAGE MonoLocalBinds #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE FlexibleContexts #-}+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}++module Control.Moffy.NoThreadId (+	-- * Applicative+	app, iapp,+	-- * Parallel+	first, at, break, until, indexBy,+	-- * Copies+	parList ) where++import Prelude hiding (break, until)+import Control.Moffy.Internal.Sig (+	app_, iapp_, at_, break_, until_, indexBy_, parList_ )+import Control.Moffy.Internal.Sig.Type (Sig, ISig)+import Control.Moffy.Internal.React (Firstable, first_)+import Control.Moffy.Internal.React.Type (React, noThreadId)+import Data.Type.Set ((:+:))+import Data.OneOrMore (Mergeable)+import Data.Or (Or)++---------------------------------------------------------------------------++-- * APPLICATIVE+-- * PARALLEL+-- * COPIES++---------------------------------------------------------------------------+-- APPLICATIVE+---------------------------------------------------------------------------++infixl 4 `app`, `iapp`++app :: ((es :+: es) ~ es, Mergeable es es es, Monoid r) =>+	Sig s es (a -> b) r -> Sig s es a r -> Sig s es b r+app = app_ noThreadId++iapp :: ((es :+: es) ~ es, Mergeable es es es, Semigroup r) =>+	ISig s es (a -> b) r -> ISig s es a r -> ISig s es b r+iapp = iapp_ noThreadId++---------------------------------------------------------------------------+-- PARALLEL+---------------------------------------------------------------------------++infixr 8 `first`++first :: Firstable es es' a b =>+	React s es a -> React s es' b -> React s (es :+: es') (Or a b)+first = first_ noThreadId++infixr 7 `at`++at :: Firstable es es' (ISig s (es :+: es') a r) r' =>+	Sig s es a r -> React s es' r' ->+	React s (es :+: es') (Either r (Maybe a, r'))+at = at_ noThreadId++infixl 7 `break`, `until`++break :: Firstable es es' (ISig s (es :+: es') a r) r' =>+	Sig s es a r -> React s es' r' ->+	Sig s (es :+: es') a (Either r (Maybe a, r'))+break = break_ noThreadId++until :: Firstable es es' (ISig s (es :+: es') a r) r' =>+	Sig s es a r -> React s es' r' ->+	Sig s (es :+: es') a (Either r (a, r'))+until = until_ noThreadId++infixl 7 `indexBy`++indexBy ::+	Firstable es es' (ISig s (es :+: es') a r) (ISig s (es :+: es') b r') =>+	Sig s es a r -> Sig s es' b r' ->+	Sig s (es :+: es') (a, b) (Either r (Maybe a, r'))+indexBy = indexBy_ noThreadId++---------------------------------------------------------------------------+-- COPIES+---------------------------------------------------------------------------++parList :: ((es :+: es) ~ es, Mergeable es es es) =>+	Sig s es (ISig s es a r) r' -> Sig s es [a] ([r], r')+parList = parList_ noThreadId
+ src/Control/Moffy/Run.hs view
@@ -0,0 +1,55 @@+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE PatternSynonyms, ViewPatterns #-}+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}++module Control.Moffy.Run (+	-- * Type+	Sig, React, Handle, HandleSt, St,+	-- * Run+	interpret, interpretSt, interpretReact, interpretReactSt ) where++import Control.Monad.Freer.Par (pattern Pure, pattern (:=<<), app)+import Control.Moffy.Internal.Sig.Type (Sig(..), isig)+import Control.Moffy.Internal.React (Adjustable, adjust)+import Control.Moffy.Internal.React.Type (+	React, Rct(..), Handle, HandleSt, liftHandle, St,+	ThreadId, rootThreadId )++---------------------------------------------------------------------------++-- * SIG+-- * REACT++---------------------------------------------------------------------------+-- SIG+---------------------------------------------------------------------------++interpret :: (Monad m, Adjustable es es') =>+	Handle m es' -> (a -> m ()) -> Sig s es a r -> m r+interpret hdl vw rqs = fst <$> interpretSt (liftHandle hdl) vw rqs ()++interpretSt :: (Monad m, Adjustable es es') =>+	HandleSt st m es' -> (a -> m ()) -> Sig s es a r -> St st m r+interpretSt hdl vw = go where+	Sig r `go` st = interpretReactSt hdl r st >>= \(i, st') ->+		isig (pure . (, st')) ((. (`go` st')) . (>>) . vw) i++---------------------------------------------------------------------------+-- REACT+---------------------------------------------------------------------------++interpretReact :: (Monad m, Adjustable es es') =>+	Handle m es' -> React s es r -> m r+interpretReact hdl rqs = fst <$> interpretReactSt (liftHandle hdl) rqs ()++interpretReactSt :: (Monad m, Adjustable es es') =>+	HandleSt st m es' -> React s es r -> St st m r+interpretReactSt hdl (adjust -> r) = runSt hdl r rootThreadId++runSt :: Monad m => HandleSt st m es -> React s es r -> ThreadId -> St st m r+runSt _ (Pure x) _ st = pure (x, st)+runSt _ (_ :=<< Never) _ _ = error "never end"+runSt hdl (c :=<< GetThreadId) t st = runSt hdl (c `app` t) t st+runSt hdl (c :=<< Await rqs) t st =+	hdl rqs st >>= \(o, st') -> runSt hdl (c `app` o) t st'
+ src/Lib.hs view
@@ -0,0 +1,6 @@+module Lib+    ( someFunc+    ) where++someFunc :: IO ()+someFunc = putStrLn "someFunc"
+ test/Spec.hs view
@@ -0,0 +1,2 @@+main :: IO ()+main = putStrLn "Test suite not yet implemented"