When function should be effectful? - functional-programming

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 return Eff.
On the other hand, a getTextContent function must return Eff. 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 return Eff, even in the rare situations where they don't need to.
Thankfully the most recent version of purescript-dom uses non-Eff functions for nodeName, tagName, localName, etc.

Effectful functions are functions that are not pure, from Wikipedia:
In computer programming, a function may be described as a pure function if both these statements about the function hold:
The function always evaluates the same result value given the same argument value(s). The function result value cannot depend on any hidden information or state that may change as program execution proceeds or between different executions of the program, nor can it depend on any external input from I/O devices [...].
Evaluation of the result does not cause any semantically observable side effect or output, such as mutation of mutable objects or output to I/O devices [...].
Since the DOM stores state, functions wrapping calls to the DOM are almost always effectful.
For more details regarding PureScript, see Handling Native Effects with the Eff Monad.

Related

Calling async function from closure

I want to await an async function inside a closure used in an iterator. The function requiring the closure is called inside a struct implementation. I can't figure out how to do this.
This code simulates what I'm trying to do:
struct MyType {}
impl MyType {
async fn foo(&self) {
println!("foo");
(0..2).for_each(|v| {
self.bar(v).await;
});
}
async fn bar(&self, v: usize) {
println!("bar: {}", v);
}
}
#[tokio::main]
async fn main() {
let mt = MyType {};
mt.foo().await;
}
Obviously, this will not work since the closure is not async, giving me:
error[E0728]: `await` is only allowed inside `async` functions and blocks
--> src/main.rs:8:13
|
7 | (0..2).for_each(|v| {
| --- this is not `async`
8 | self.bar(v).await;
| ^^^^^^^^^^^^^^^^^ only allowed inside `async` functions and blocks
After looking for an answer on how to call an async function from a non-async one, I eded up with this:
tokio::spawn(async move {
self.bar(v).await;
});
But now I'm hitting lifetime issues instead:
error[E0759]: `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
--> src/main.rs:4:18
|
4 | async fn foo(&self) {
| ^^^^^
| |
| this data with an anonymous lifetime `'_`...
| ...is captured here...
...
8 | tokio::spawn(async move {
| ------------ ...and is required to live as long as `'static` here
This also doesn't surprise me since from what I understand the Rust compiler cannot know how long a thread will live. Given this, the thread spawned with tokio::spawn might outlive the type MyType.
The first fix I came up with was to make bar an associate function, copy everything I need in my closure and pass it as a value to bar and call it with MyType::bar(copies_from_self) but this is getting ugly since there's a lot of copying. It also feels like a workaround for not knowing how lifetimes work.
I was instead trying to use futures::executor::block_on which works for simple tasks like the one in this post:
(0..2).for_each(|v| {
futures::executor::block_on(self.bar(v));
});
But when putting this in my real life example where I use a third party library1 which also uses tokio, things no longer work. After reading the documentation, I realise that #[tokio::main] is a macro that eventually wraps everything in block_on so by doing this there will be nested block_on. This might be the reason why one of the async methods called in bar just stops working without any error or logging (works without block_on so shouldn't be anything with the code). I reached out to the authors who said that I could use for_each(|i| async move { ... }) which made me even more confused.
(0..2).for_each(|v| async move {
self.bar(v).await;
});
Will result in the compilation error
expected `()`, found opaque type`
which I think makes sense since I'm now returning a future and not (). My naive approach to this was to try and await the future with something like this:
(0..2).for_each(|v| {
async move {
self.bar(v).await;
}
.await
});
But that takes me back to square one, resulting in the following compilation error which I also think makes sense since I'm now back to using await in the closure which is sync.
only allowed inside `async` functions and blocks` since the
This discovery also makes it hard for me to make use of answers such as the ones found here and here.
The question after all this cargo cult programming is basically, is it possible, and if so how do I call my async function from the closure (and preferably without spawning a thread to avoid lifetime problems) in an iterator? If this is not possible, what would an idiomatic implementation for this look like?
1This is the library/method used
Iterator::for_each expects a synchronous closure, thus you can't use .await in it (not directly at least), nor can you return a future from it.
One solution is to just use a for loop instead of .for_each:
for v in 0..2 {
self.bar(v).await;
}
The more general approach is to use streams instead of iterators, since those are the asynchronous equivalent (and the equivalent methods on streams are typically asynchronous as well). This would work not only for for_each but for most other iterator methods:
use futures::prelude::*;
futures::stream::iter(0..2)
.for_each(|c| async move {
self.bar(v).await;
})
.await;

Should I return await in Rust?

In JavaScript, async code is written with Promises and async/await syntax similar to that of Rust. It is generally considered redundant (and therefore discouraged) to return and await a Promise when it can simply be returned (i.e., when an async function is executed as the last thing in another function):
async function myFn() { /* ... */ }
async function myFn2() {
// do setup work
return await myFn()
// ^ this is not necessary when we can just return the Promise
}
I am wondering whether a similar pattern applies in Rust. Should I prefer this:
pub async fn my_function(
&mut self,
) -> Result<()> {
// do synchronous setup work
self.exec_command(
/* ... */
)
.await
}
Or this:
pub fn my_function(
&mut self,
) -> impl Future<Output = Result<()>> {
// do synchronous setup work
self.exec_command(
/* ... */
)
}
The former feels more ergonomic to me, but I suspect that the latter might be more performant. Is this the case?
One semantic difference between the two variants is that in the first variant the synchronous setup code will run only when the returned future is awaited, while in the second variant it will run as soon as the function is called:
let fut = x.my_function();
// in the second variant, the synchronous setup has finished by now
...
let val = fut.await; // in the first variant, it runs here
For the difference to be noticeable, the synchronous setup code must have side effects, and there needs to be a delay between calling the async function and awaiting the future it returns.
Unless you have specific reason to execute the preamble immediately, go with the async function, i.e. the first variant. It makes the function slightly more predictable, and makes it easier to add more awaits later as the function is refactored.
There is no real difference between the two since async just resolves down to impl Future<Output=Result<T, E>>. I don't believe there is any meaningful performance difference between the two, at least in my empirical usage of both.
If you are asking for preference in style then in my opinion the first one is preferred as the types are clearer to me and I agree it is more ergonomic.

Hashable tuple-like collections in TypeScript

I'm writing a (toy) hash-and-cache decorator in TypeScript and can't find a good means of creating a solid generic one.
The code I have so far is
function cache
(target: Object,
propertyKey: string,
// Likely we can do better than <any> here -- <Function<any>> maybe?
descriptor: TypedPropertyDescriptor<any>)
{
let cacheMap = new Map();
let wrappedFn = descriptor.value;
descriptor.value = function (...args: any[]) {
if (cacheMap.has(args)) {
console.log("Short-circuiting with result: " + cacheMap.get(args));
return cacheMap.get(args);
}
let result = wrappedFn.apply(this, args);
cacheMap.set(args, result);
console.log("cacheMap %o", cacheMap);
return result;
}
return descriptor;
}
Naturally this fails, since args is not a tuple but a list, which is mutable[1]. So each input, even if it's the same over and over, gets its own list/array in its own memory location with its own hash value, wherever that comes from.
I haven't found a Tuple type in TypeScript (or JS) yet -- is there one? Is there another workaround for this sort of problem?
Shouldn't this be an error? Map<T, U> should constrain T to implementing IHashable or something, right? That's the point of types -- to raise this issue before it takes a bunch of time out of your life.
Shouldn't this be an error? Map<T, U> should constrain T to implementing IHashable or something, right?
No. Object identity is a real and well-defined thing in JavaScript; TypeScript doesn't attempt to force you to pretend it doesn't exist.
If the ECMAScript committee thought it was appropriate to enforce non-object-identity-based keying in maps, they could have restricted Map keys, but they didn't.

How do I type a function with input and output objects with the same keys but different value types?

Basically, I have a function that will transform an object into a different object, and it's like a dictionary, but I don't know how to type it.
var myFunctions = {
a: () => something1,
b: () => something2,
[...]
}
gets transformed into
var myObject = {
a: something1,
b: something2
[...]
}
With Flow 0.33+ you can use $ObjMap
type ExtractCodomain = <V>(v: () => V) => V;
declare function f<O>(o: O): $ObjMap<O, ExtractCodomain>;
I don't think you can do this with Flow. The closest you can get is probably this:
function<T>(obj: T): ([key: $Keys<T>]: boolean)
That function is typed to return an object with the same key as input object, but with boolean-only values (as an example, you can specify another type). Sorry to disappoint, but it's hard to type highly dynamic code with Flow in general.
Note that the $Keys feature is undocumented because it's not part of the public API, so its behavior is defined solely by its implementation (in other words, it can change anytime).
If you're interested in the details of Flow's type system, check out the typings that come with flow in its own /lib directory, for example https://github.com/facebook/flow/blob/master/lib/core.js – you'll see that some things like Object.assign are special-cased, so you might not be able to re-implement such things in your own code.
Also, check out http://sitr.us/2015/05/31/advanced-features-in-flow.html for other "dollar features" such as $Shape and $Diff – it's partially outdated, but can give some good pointers.
#Nikita gave you the best answer for now. That said, the use-case you talked about is being discussed in the issues on the FlowType repository. It may land soon.
As of right now, if you've got mixed type, I'll just fallback to any
function<T>(obj: T): ([key: $Keys<T>]: any)
This way, at least the key names are validated. I expect within a few more versions of Flow, this problem will get solved.

What is the purpose of the state monad?

I am a JavaScript developer on a journey to up my skills in functional programming. I recently ran into a wall when it comes to managing state. When searching for a solution I stumbeled over the state monad in various articles and videos but I have a really hard time understanding it. I am wondering if it is because I expect it to be something it is not.
The problem I am trying to solve
In a web client I am fetching resources from the back end. To avoid unnecessary traffic I am creating a simple cache on the client side which contains the already fetched data. The cache is my state. I want several of my modules to be able to hold a reference to the cache and query it for its current state, a state that may have been modified by another module.
This is of course not a problem in javascript since it is possible to mutate state but I would like to learn more about functional programming and I was hoping that the state monad would help me.
What I would expect
I had assume that I could do something like this:
var state = State.of(1);
map(add(1), state);
state.evalState() // => 2
This obviously doesn't work. The state is always 1.
My question
Are my assumptions about the state monad wrong, or am I simply using it incorrectly?
I realize that I can do this:
var state = State.of(1);
var newState = map(add(1), state);
... and newState will be a state of 2. But here I don't really see the use of the state monad since I will have to create a new instance in order for the value to change. This to me seems to be what is always done in functional programming where values are immutable.
The purpose of the state monad is to hide the passing of state between functions.
Let's take an example:
The methods A and B need to use some state and mutate it, and B needs to use the state that A mutated. In a functional language with immutable data, this is impossible.
What is done instead is this: an initial state is passed to A, along with the arguments it needs, and A returns a result and a "modified" state -- really a new value, since the original wasn't changed. This "new" state (and possibly the result too) is passed into B with its required arguments, and B returns its result and a state that it (may have) modified.
Passing this state around explicitly is a PITA, so the State monad hides this under its monadic covers, allowing methods which need to access the state to get at it through get and set monadic methods.
To use the stateful computations A and B, we combine them together into a conglomerate stateful computation and give that conglomerate a beginning state (and arguments) to run with, and it returns a final "modified" state and result (after running things through A, B, and whatever else it was composed of).
From what you're describing it seems to me like you're looking for something more along the lines of the actor model of concurrency, where state is managed in an actor and the rest of the code interfaces with it through that, retrieving (a non-mutable version of) it or telling it to be modified via messages. In immutable languages (like Erlang), actors block waiting for a message, then process one when it comes in, then loop via (tail) recursion; they pass any modified state to the recursive call, and this is how the state gets "modified".
As you say, though, since you're using JavaScript it's not much of an issue.
I'm trying to answer your question from the perspective of a Javascript developer, because I believe that this is the cause of your problem. Maybe you can specify the term Javascript in the headline and in the tags.
Transferring of concepts from Haskell to Javascript is basically a good thing, because Haskell is a very mature, purely functional language. It can, however, lead to confusion, as in the case of the state monad.
The maybe monad for instance can be easily understood, because it deals with a problem that both languages are facing: Computations that might go wrong by not returning a value (null/undefined in Javascript). Maybe saves developers from scattering null checks throughout their code.
In the case of the state monad the situation is a little different. In Haskell, the state monad is required in order to compose functions, which share changeable state, without having to pass this state around. State is one or more variables that are not among the arguments of the functions involved. In Javascript you can just do the following:
var stack = {
store: [],
push: function push(element) { this.store.push(element); return this; },
pop: function pop() { return this.store.pop(); }
}
console.log(stack.push(1).push(2).push(3).pop()); // 3 (return value of stateful computation)
console.log(stack.store); // [1, 2] (mutated, global state)
This is the desired stateful computation and store does not have to be passed around from method to method. At first sight there is no reason to use the state monad in Javascript. But since store is publicly accessible, push and pop mutate global state. Mutating global state is a bad idea. This problem can be solved in several ways, one of which is precisely the state monad.
The following simplified example implements a stack as state monad:
function chain(mv, mf) {
return function (state) {
var r = mv(state);
return mf(r.value)(r.state);
};
}
function of(x) {
return function (state) {
return {value: x, state: state};
};
}
function push(element) {
return function (stack) {
return of(null)(stack.concat([element]));
};
}
function pop() {
return function (stack) {
return of(stack[stack.length - 1])(stack.slice(0, -1));
};
}
function runStack(seq, stack) { return seq(stack); }
function evalStack(seq, stack) { return seq(stack).value; }
function execStack(seq, stack) { return seq(stack).state; }
function add(x, y) { return x + y; }
// stateful computation is not completely evaluated (lazy evaluation)
// no state variables are passed around
var computation = chain(pop(), function (x) {
if (x < 4) {
return chain(push(4), function () {
return chain(push(5), function () {
return chain(pop(), function (y) {
return of(add(x, y));
});
});
});
} else {
return chain(pop(), function (y) {
return of(add(x, y));
});
}
});
var stack1 = [1, 2, 3],
stack2 = [1, 4, 5];
console.log(runStack(computation, stack1)); // Object {value: 8, state: Array[3]}
console.log(runStack(computation, stack2)); // Object {value: 9, state: Array[1]}
// the return values of the stateful computations
console.log(evalStack(computation, stack1)); // 8
console.log(evalStack(computation, stack2)); // 9
// the shared state within the computation has changed
console.log(execStack(computation, stack1)); // [1, 2, 4]
console.log(execStack(computation, stack2)); // [1]
// no globale state has changed
cosole.log(stack1); // [1, 2, 3]
cosole.log(stack2); // [1, 4, 5]
The nested function calls could be avoided. I've omitted this feature for simplicity.
There is no issue in Javascript that can be solved solely with the state monad. And it is much harder to understand something as generalized as the state monad, that solves a seemingly non-existing problem in the used language. Its use is merely a matter of personal preference.
It indeed works like your second description where a new immutable state is returned. It isn't particularly useful if you call it like this, however. Where it comes in handy is if you have a bunch of functions you want to call, each taking the state returned from the previous step and returning a new state and possibly another value.
Making it a monad basically allows you to specify a list of just the function names to be executed, rather than repeating the newState = f(initialState); newNewState = g(newState); finalState = h(newNewState); over and over. Haskell has a built-in notation called do-notation to do precisely this. How you accomplish it in JavaScript depends on what functional library you're using, but in its simplest form (without any binding of intermediate results) it might look something like finalState = do([f,g,h], initialState).
In other words, the state monad doesn't magically make immutability look like mutability, but it can simplify the tracking of intermediate states in certain circumstances.
State is present everywhere. In class, it could be the value of its properties. In programs it could be the value of variables. In languages like javascript and even java which allow mutability, we pass the state as arguments to the mutating function. However, in languages such as Haskell and Scala, which do not like mutation(called as side-effects or impure), the new State (with the updates) is explicitly returned which is then passed to its consumers. In order to hide this explicit state passes and returns, Haskell(and Scala) had this concept of State Monad. I have written an article on the same at https://lakshmirajagopalan.github.io/state-monad-in-scala/

Resources