When I use FFI to wrap some API (for example DOM API) is there any rule of thumb that could help me to decide whether function should be effectful or not?
Here is an example:
foreign import querySelectorImpl """
function querySelectorImpl (Nothing) {
return function (Just) {
return function (selector) {
return function (src) {
return function () {
var result = src.querySelector(selector);
return result ? Just(result) : Nothing;
};
};
};
};
}
""" :: forall a e. Maybe a -> (a -> Maybe a) -> String -> Node -> Eff (dom :: DOM | e) (Maybe Node)
querySelector :: forall e. String -> Node -> Eff (dom :: DOM | e) (Maybe Node)
querySelector = querySelectorImpl Nothing Just
foreign import getTagName """
function getTagName (n) {
return function () {
return n.tagName;
};
}
""" :: forall e. Node -> Eff (dom :: DOM | e) String
It feels right for querySelector
to be effectful, but I'm not quite sure about getTagName
Update:
I understand what a pure function is and that it should not change the state of the program and maybe DOM was a bad example.
I ask this question because in most libraries that wrap existing js libraries pretty much every function is effectful even if it doesn't feels right. So maybe my actual question is - does this effect represent the need in this wrapped js lib or is it there just in case it is stateful inside?
If a function does not change state, and it always (past, present, and future) returns the same value when given the same arguments, then it does not need to return
Eff
, otherwise it does.n.tagName
is read-only, and as far as I know, it never changes. Therefore,getTagName
is pure, and it's okay to not returnEff
.On the other hand, a
getTextContent
function must returnEff
. It does not change state, but it does return different values at different times.The vast vast vast majority of JS APIs (including the DOM) are effectful.
getTagName
is one of the very few exceptions. So when writing an FFI, PureScript authors just assume that all JS functions returnEff
, even in the rare situations where they don't need to.Thankfully the most recent version of
purescript-dom
uses non-Eff
functions fornodeName
,tagName
,localName
, etc.