Skip to content

Commit af0d1f2

Browse files
Implement minimal listener, emitter, and subscriptions
1 parent be63aa4 commit af0d1f2

File tree

5 files changed

+101
-12
lines changed

5 files changed

+101
-12
lines changed

package.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"private": true,
3+
"scripts": {
4+
"build": "spago build --purs-args '--censor-lib --strict'",
5+
"test": "spago -x test/test.dhall test"
6+
},
7+
"devDependencies": {
8+
"purescript": "^0.14.0",
9+
"purescript-psa": "^0.8.2",
10+
"spago": "^0.19.1"
11+
}
12+
}

spago.dhall

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
{ name = "halogen-emitter"
2-
, dependencies = [ "effect" ]
2+
, dependencies =
3+
[ "arrays"
4+
, "effect"
5+
, "foldable-traversable"
6+
, "functors"
7+
, "refs"
8+
, "safe-coerce"
9+
, "unsafe-reference"
10+
]
311
, packages = ./packages.dhall
4-
, sources = [ "src/**/*.purs", "test/**/*.purs" ]
12+
, sources = [ "src/**/*.purs" ]
513
}

src/Halogen/Emitter.purs

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
module Halogen.Emitter
2+
( EmitIO(..)
3+
, Listener
4+
, notify
5+
, Emitter
6+
, create
7+
, makeEmitter
8+
, Subscription
9+
, subscribe
10+
, unsubscribe
11+
) where
12+
13+
import Prelude
14+
15+
import Data.Array (deleteBy)
16+
import Data.Foldable (traverse_)
17+
import Data.Functor.Contravariant (class Contravariant)
18+
import Effect (Effect)
19+
import Effect.Ref as Ref
20+
import Safe.Coerce (coerce)
21+
import Unsafe.Reference (unsafeRefEq)
22+
23+
type EmitIO a =
24+
{ listener :: Listener a
25+
, emitter :: Emitter a
26+
}
27+
28+
newtype Listener a = Listener (a -> Effect Unit)
29+
30+
instance contravariantListener :: Contravariant Listener where
31+
cmap f (Listener g) = Listener (g <<< f)
32+
33+
notify :: forall a. a -> Listener a -> Effect Unit
34+
notify a (Listener f) = f a
35+
36+
newtype Emitter a = Emitter ((a -> Effect Unit) -> Effect Subscription)
37+
38+
instance functorEmitter :: Functor Emitter where
39+
map f (Emitter e) = Emitter \k -> e (k <<< f)
40+
41+
create :: forall a. Effect (EmitIO a)
42+
create = do
43+
subscribers <- Ref.new []
44+
pure
45+
{ emitter: Emitter \k -> do
46+
_ <- Ref.modify (_ <> [k]) subscribers
47+
pure $ Subscription do
48+
_ <- Ref.modify (deleteBy unsafeRefEq k) subscribers
49+
pure unit
50+
, listener: Listener \a -> do
51+
Ref.read subscribers >>= traverse_ \k -> k a
52+
}
53+
54+
makeEmitter
55+
:: forall a
56+
. ((a -> Effect Unit) -> Effect (Effect Unit))
57+
-> Emitter a
58+
makeEmitter = coerce
59+
60+
newtype Subscription = Subscription (Effect Unit)
61+
62+
derive newtype instance semigroupSubscription :: Semigroup Subscription
63+
derive newtype instance monoidSubscription :: Monoid Subscription
64+
65+
subscribe
66+
:: forall r a
67+
. Emitter a
68+
-> (a -> Effect r)
69+
-> Effect Subscription
70+
subscribe (Emitter e) k = e (void <<< k)
71+
72+
unsubscribe :: Subscription -> Effect Unit
73+
unsubscribe (Subscription unsub) = unsub

src/Main.purs

Lines changed: 0 additions & 10 deletions
This file was deleted.

test/test.dhall

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
let conf = ../spago.dhall
2+
3+
in conf // {
4+
sources = conf.sources # [ "test/**/*.purs" ],
5+
dependencies = conf.dependencies # [ "assert", "console" ]
6+
}

0 commit comments

Comments
 (0)