EffObject
- Package
- purescript-eff-object
- Repository
- hdgarrood/purescript-eff-object
This module contains declarations and some basic functions to allow you to give PureScript types to stateful or otherwise effectful JavaScript APIs like XMLHttpRequest or WebSocket without writing a ton of error-prone and tedious FFI code.
For example, if you wanted to provide a low-level typing for the XMLHttpRequest web API, you might write the following:
type XMLHttpRequest e =
EffObject
-- The first type argument contains effects associated with interacting
-- with the object. Interacting with an XHR uses an AJAX effect, so
-- we record this here.
( ajax :: AJAX )
-- We record the properties as well as their types and access levels
-- in the second type argument.
( onreadystatechange :: ReadWrite (Eff e Unit)
, readyState :: ReadOnly Int
, response :: ReadOnly (Nullable Response)
, [...]
)
Consumers of your API can now interact with an XMLHttpRequest
object
using the readProperty
or writeProperty
functions:
checkReadyState ::
forall e.
XMLHttpRequest e ->
Eff (ajax :: AJAX | e) String
checkReadyState req = do
s <- readProperty (SProxy :: SProxy "readyState") req
pure $ if (s == done)
then "Done!"
else "Not done."
where
done = 4
Attempting to write read-only properties will produce a custom type error explaining what happened:
oops :: forall e. XMLHttpRequest e -> Eff (ajax :: AJAX | e) Unit
oops req = writeProperty (SProxy :: SProxy "readyState") req 0
-- Throws:
-- A custom type error occurred while solving type class constraints:
-- Cannot write to a read-only property.
Note that any APIs constructed using this library will necessarily be
very low-level; you might want to build extra layers above this API, for
instance, to provide a real ReadyState
type which is guaranteed to only
take values which would be valid the for readyState
property itself.
#EffObject Source
data EffObject (e :: Row Effect) (props :: Row Type)
A JavaScript object, with properties which can be read or written. The type arguments track:
e
: Effects associated with reading or writing propertiesprops
: Properties.
The labels in the props
row type must correspond exactly to the property
names on the underlying object, and the types in the props
row should
be of the form ReadOnly a
, WriteOnly a
, or ReadWrite a
, depending
on the access level, and where a
is the type of the property's value.
#readProperty Source
readProperty :: forall a access name props' props prop e. IsSymbol name => Readable access => RowCons name prop props' props => TypeEquals prop (access a) => SProxy name -> EffObject e props -> Eff e a
Read a property from an EffObject
.
#writeProperty Source
writeProperty :: forall a access name props' props prop e. IsSymbol name => Writeable access => RowCons name prop props' props => TypeEquals prop (access a) => SProxy name -> EffObject e props -> a -> Eff e Unit
Write a property to an EffObject
.
#BoundFunction Source
newtype BoundFunction (receiver :: Type) (fn :: Type)
A function which should be called with a this
value which is a specific
type. The fn
type argument should generally either be an
EffFn
from purescript-eff
, or a Fn
from purescript-functions
.
#mkBoundFunction Source
mkBoundFunction :: forall receiver fn. fn -> BoundFunction receiver fn
Wrap a function in a BoundFunction
constructor to ensure that it may only
be called with a this
value of the type receiver
.
#bindTo Source
bindTo :: forall receiver fn. receiver -> BoundFunction receiver fn -> fn
Run a BoundFunction
by providing a this
object.
#Self Source
data Self
This type provides a way of saying that a BoundFunction
which is a
property of some EffObject
should receive that EffObject
as its this
value when called.
#BoundMethod Source
type BoundMethod fn = BoundFunction Self fn
#bindProperty Source
bindProperty :: forall fn access name props' props prop e. IsSymbol name => Readable access => RowCons name prop props' props => TypeEquals prop (access (BoundMethod fn)) => SProxy name -> EffObject e props -> Eff e fn
- Modules
- EffObject