mirror of
https://github.com/urbit/shrub.git
synced 2024-12-22 10:21:31 +03:00
b3901ab42f
git-subtree-dir: pkg/arvo git-subtree-mainline:9c8f40bf6c
git-subtree-split:c20e2a185f
87 lines
2.4 KiB
Plaintext
87 lines
2.4 KiB
Plaintext
:: Defines the ph monad.
|
|
::
|
|
:: A complete ph test has type data:(ph ,~). This is a function that
|
|
:: accepts a new unix-effect and produces a list of ph-events to inject
|
|
:: back into the system. It also produces one of four "next steps":
|
|
::
|
|
:: %wait: no change; on next unix-effect call this same function.
|
|
:: %cont: swap out this test for another one. Mainly useful for
|
|
:: the implementation of +bind.
|
|
:: %fail: the test has failed.
|
|
:: %done: the test has finished successfully.
|
|
::
|
|
:: When producing %done, you may specify a value. The ph app assumes
|
|
:: the value of each whole test will be ~. During the test, though, it
|
|
:: may be useful to produce intermediate values.
|
|
::
|
|
:: We define two additional functions. +return takes a value and
|
|
:: produces a test which immediately produces a %done with that value.
|
|
::
|
|
:: +bind takes a test and a function from the output type of that test
|
|
:: to another test. This is useful to link tests together. See
|
|
:: lib/ph/tests.hoon for examples of usage.
|
|
::
|
|
:: You may recognize monad terminology. These functions satisfy the
|
|
:: monad laws: If `f` and `g` are the sort of function that go in the
|
|
:: second argument to bind and `m` is a test, then:
|
|
::
|
|
:: (cork pure (curr bind f)) = f
|
|
:: (bind m pure) = m
|
|
:: ((bind m f) g) = (bind m (bind f g))
|
|
::
|
|
:: Maintaining these laws requires a particular interpretation of the
|
|
:: monad, which the ph app implements in +diff-aqua-effects. Thus,
|
|
:: within the ph app the monad laws hold.
|
|
::
|
|
/- aquarium
|
|
=, aquarium
|
|
|%
|
|
+$ ph-input
|
|
[now=@da who=ship uf=unix-effect]
|
|
::
|
|
++ ph-output-raw
|
|
|* a=mold
|
|
$~ [& ~ %done *a]
|
|
$: thru=?
|
|
events=(list ph-event)
|
|
$= next
|
|
$% [%wait ~]
|
|
[%cont self=(ph-form-raw a)]
|
|
[%fail ~]
|
|
[%done value=a]
|
|
==
|
|
==
|
|
::
|
|
++ ph-form-raw
|
|
|* a=mold
|
|
$-(ph-input (ph-output-raw a))
|
|
::
|
|
++ ph
|
|
|* a=mold
|
|
|%
|
|
++ output (ph-output-raw a)
|
|
++ form (ph-form-raw a)
|
|
++ pure
|
|
|= arg=a
|
|
^- form
|
|
|= ph-input
|
|
[& ~ %done arg]
|
|
::
|
|
++ bind
|
|
|* b=mold
|
|
|= [m-b=(ph-form-raw b) fun=$-(b form)]
|
|
^- form
|
|
|= input=ph-input
|
|
=/ b-res=(ph-output-raw b)
|
|
(m-b input)
|
|
^- output
|
|
:+ thru.b-res events.b-res
|
|
?- -.next.b-res
|
|
%wait [%wait ~]
|
|
%cont [%cont ..$(m-b self.next.b-res)]
|
|
%fail [%fail ~]
|
|
%done [%cont (fun value.next.b-res)]
|
|
==
|
|
--
|
|
--
|