I want to declare a parameter type as Maybe a function with a default value of undefined.
However I am getting Flow errors as neither undefined or null are considered to be of type function.
Is there are way to do this?
This is how I would implement a function that executes a given function, unless the given function is undefined:
function maybeExecute<A: *, R>(f: ?(...args: A) => R, ...args: A): ?R {
if (f) {
return f(...args)
}
}
That type-checks in Flow v0.64.0. The use of the ? indicates that f might be undefined or null. The if (f) { /* ... */ } check narrows the type of f so that inside the body of the if Flow can guarantee that f is a function.
You can get a little fancier and declare multiple signatures to make maybeExecute an overloaded function like this:
declare function maybeExecute<A: *, R>(f: (...args: A) => R, ...args: A): R
declare function maybeExecute(f: null | void, ...args: mixed[]): void
function maybeExecute(f, ...args) {
if (f) {
return f(...args)
}
}
With the overloaded version if Flow is able to infer that the given function was defined then it may be able to infer that the return value of maybeExecute is also defined.
Related
Note: I started a discussion on Github about this subject.
I have a zip function, for now it is typed for iterables of the same type T. I would like to have this typed for arbitrary mixed input type but still conserving the matching output type, for example, if the input type [Iterable<T>, Iterable<U>] I want the output type to be Iterable<[T, U]>. Is it possible to have this for arbitrary input size? I basically want to say, if you have this list of type as input you'll have them as output.
Here is the current version of my zip:
export function *zip<T>(...iterables:Array<Iterable<T>>): Iterable<Array<T>> {
const iterators = iterables.map(iterable => iter(iterable));
while(true){
const items = iterators.map(iterator => iterator.next());
if (items.some(item => item.done)){
return;
}
yield ((items.map(item => { return item.value }): Array<any>): Array<T>);
}
}
export function *iter<T>(iterable:Iterable<T>): Iterator<T> {
yield* iterable;
}
Current best solution by AndrewSouthpaw:
declare function zip<A, B>(Iterable<A>, Iterable<B>): Iterable<[A, B]>;
declare function zip<A, B, C>(Iterable<A>, Iterable<B>, Iterable<C>): Iterable<[A, B, C]>;
declare function zip<A, B, C, D>(Iterable<A>, Iterable<B>, Iterable<C>, Iterable<D>): Iterable<[A, B, C, D]>;
export function *zip<T>(...iterables:Array<Iterable<T>>): Iterable<Array<T>> {
const iterators = iterables.map(iterable => iter(iterable));
while(true){
const items = iterators.map(iterator => iterator.next());
if (items.some(item => item.done)){
return;
}
yield ((items.map(item => { return item.value }): Array<any>): Array<T>);
}
}
It works as expected when called with 4, 3 or 2 iterables, when called with 5 or more arguments flow will simply say that zip can only be called with 4 or less arguments. Of course we could add as many function signature as we like to get it to work for 5, 6 or any number N of arguments, but that would require to declare N distinct signatures (which is a bit ugly). On the other hand this strategy does not allow to have an unbounded number of arguments (like the spread operator does). I'm still looking for that.
This raised a more general question, is there any language in which this exists?
I really have the feeling that this can be done in theory (not necessarily in flow), on the other hand I can't recall of a statically typed language in which I've done/seen that (I would also be interested in seeing this kind of type checking in any language).
To be a bit more specific, my feeling is that if you have a type checking system in which (by definition) all types are statically known (any variable has a known type x) then function f: Array<Iterable<x>> -> Iterable<Array<x>> is always called on a known type x. Therefore we should be able to statically decide what type f will return given x (whether x is a single generic type or a list of generic types).
The same goes for the function itself, if you have a type x as input, then you only need to check that your function preserve type x.
Maybe this needs to be defined recursively in some languages, that would also be interesting to see.
We've only been able to accomplish this through overriding the function signature declaration. This might help:
declare function zip<A, B>(Iterable<A>, Iterable<B>): Iterable<[A, B]>
declare function zip<A, B, C>(Iterable<A>, Iterable<B>, Iterable<C>): Iterable<[A, B, C]>
declare function zip<A, B, C, D>(Iterable<A>, Iterable<B>, Iterable<C>, Iterable<D>): Iterable<[A, B, C, D]>
export function zip(a, b, c, d) {
/* ... */
}
Here is the working solution. All credit goes to jbrown215 from Flow team, he found the idea of using $ReadOnlyArray<mixed> here:
export function *zip<T: $ReadOnlyArray<mixed>>(...iterables:Array<Iterable<T>>): Iterable<Array<T>> {
const iterators = iterables.map(iterable => iter(iterable));
while(true){
const items = iterators.map(iterator => iterator.next());
if (items.some(item => item.done)){
return;
}
yield ((items.map(item => { return item.value }): Array<any>): Array<T>);
}
}
export function *iter<T>(iterable:Iterable<T>): Iterator<T> {
yield* iterable;
}
There are similar questions here but they are attached to a particular programming language and I am looking for an answer on the conceptual level.
As I understand, Functors are essentially immutable containers that expose map() API which derives another functor. Which addition makes it possible to call a particular functor a monad?
As I understand, every monad is a functor but not every functor is a monad.
Let me explain my understanding without going into category theory:
Functors and monads both provide some tool to wrapped input, returning a wrapped output.
Functor = unit + map (i.e. the tool)
where,
unit = something which takes raw input and wraps it inside a small context.
map = the tool which takes a function as input, applies it to raw value in wrapper, and returns wrapped result.
Example: Let us define a function which doubles an integer
// doubleMe :: Int a -> Int b
const doubleMe = a => 2 * a;
Maybe(2).map(doubleMe) // Maybe(4)
Monad = unit + flatMap (or bind or chain)
flatMap = the tool which flattens the map, as its name implies. It will be clear soon with the example below.
Example: Let us say we have a curried function which appends two strings only if both are not blank.
Let me define one as below:
append :: (string a,string b) -> Maybe(string c)
Let's now see the problem with map (the tool that comes with Functor),
Maybe("a").map(append("b")) // Maybe(Maybe("ab"))
How come there are two Maybes here?
Well, that's what map does; it applies the provided function to the wrapped value and wraps the result.
Let's break this into steps,
Apply the mapped function to the wrapped value
; here the mapped function is append("b") and the wrapped value is "a", which results in Maybe("ab").
Wrap the result, which returns Maybe(Maybe("ab")).
Now the value we are interested in is wrapped twice. Here comes flatMap to the rescue.
Maybe("a").flatMap(append("b")) // Maybe("ab")
Of course, functors and monads have to follow some other laws too, but I believe this is not in the scope of what is asked.
Swift Functor, Applicative, Monad
Functor, Applicative, Monad:
solve the same problem - working with a wrapped value into context(class)
using closure[About]
return a new instance of context(class)
The difference is in parameters of closure
Pseudocode:
class SomeClass<T> {
var wrappedValue: T //wrappedValue: - wrapped value
func foo<U>(function: ???) -> Functor<U> { //function: - function/closure
//logic
}
}
where ???
function: (T) -> U == Functor
function: SomeClass< (T) -> U > == Applicative
function: (T) -> SomeClass<U> == Monad
Functor
Functor applies a function to a wrapped value
Pseudocode:
class Functor<T> {
var value: T
func map<U>(function: (T) -> U) -> Functor<U> {
return Functor(value: function(value)) //<- apply a function to value
}
}
Applicative or applicative functor
Applicative applies wrapped function to a wrapped value.
The diff with Functor is wrapped function instead of function
Pseudocode:
class Applicative<T> {
var value: T
func apply<U>(function: Applicative< (T) -> U >) -> Applicative<U> {
return Applicative(value: unwrappedFunction(value))
}
}
Monad
Monad applies a function(which returns a wrapped value) to a wrapped value
Pseudocode:
class Monad<T> {
var value: T
func flatMap<U>(function: (T) -> Monad<U>) -> Monad<U> { //function which returns a wrapped value
return function(value) //applies the function to a wrapped value
}
}
Swift:
Optional, Collection, Result is Functor and Monad
String is Functor
Optional as an example
enum CustomOptional<T> {
case none
case some(T)
public init(_ some: T) {
self = .some(some)
}
//CustomOptional is Functor
func map<U>(_ transform: (T) -> U) -> CustomOptional<U> {
switch self {
case .some(let value):
let transformResult: U = transform(value)
let result: CustomOptional<U> = CustomOptional<U>(transformResult)
return result
case .none:
return .none
}
}
//CustomOptional is Applicative
func apply<U>(transformOptional: CustomOptional<(T) -> U>) -> CustomOptional<U> {
switch transformOptional {
case .some(let transform):
return self.map(transform)
case .none:
return .none
}
}
//CustomOptional is Monad
func flatMap<U>(_ transform: (T) -> CustomOptional<U>) -> CustomOptional<U> {
switch self {
case .some(let value):
let transformResult: CustomOptional<U> = transform(value)
let result: CustomOptional<U> = transformResult
return result
case .none:
return .none
}
}
}
[Swift Optional map vs flatMap]
(Note that this will be a simplified explanation for category theory concepts)
Functor
A Functor is a function from a set of values a to another set of values: a -> b. For a programming language this could be a function that goes from String -> Integer:
function fn(text: string) : integer
Composition
Composition is when you use the value of one function as input to the value of the next: fa(fb(x)). For example:
hash(lowercase(text))
Monads
A Monad allows to compose Functors that either are not composable otherwise, compose Functors by adding extra functionality in the composition, or both.
An example of the first is a Monad for a Functor String -> (String, Integer)
An example of the second is a Monad that counts the Number of functions called on a value
A Monad includes a Functor T that is responsible for the functionality you want plus two other functions:
input -> T(input)
T(T(input)) -> T(input)
The first function allows to transform your input values to a set of values that our Monad can compose. The second function allows for the composition.
So in conclusion, every Monad is not a Functor but uses a Functor to complete it's purpose.
This is how you annotate a variable / constant as holding a function of a particular type:
declare type TFunction = () => any;
const foo: TFunction = function foo() {};
What is the syntax when one declares a function:
function boo() {}
?
There's no way to put: TFunction on your function boo() declaration. However, you can flow check it by writing the no-op statement (boo: TFunction); afterward. The only drawback is this evaluates boo at runtime.
Probably the best way to do it though is to not worry about explicitly declaring that boo is a TFunction, and instead just rely on Flow to check it any time you use boo where a TFunction is expected.
Here's a more concrete example of what I mean: (Try flow link)
/* #flow */
type ArithmeticOperation = (a: number, b: number) => number;
function add(a: number, b: number): number {
return a + b;
}
function concat(a: string, b: string): string {
return a + b;
}
function fold(array: Array<number>, operation: ArithmeticOperation): number {
return array.reduce(operation);
}
fold([1, 2, 3], add); // ok because add matches ArithmeticOperation
fold([1, 2, 3], concat); // flow error because concat doesn't match
Coming late to this question, but if you are talking about declarations in the sense of "compile-time declarations, separate from code, that use the declare keyword", then per the Flow declarations docs, you should be able to declare globals like this:
declare var boo: TFunction;
or scoped items as members of their containing module or type:
declare class FunctionHolder {
boo: TFunction;
}
I would like to declare the type of a function using a type alias. Something like this:
type F = (_: number) => number;
function f:F (a) { return a; }
^ Unexpected token :
declare function f:F;
^ Unexpected token :
The reason I want this is that I have a bunch of functions with the same (rather long) type declaration and I'd like to save the typing and improve the clarity.
Is it possible to do this in Flow? If no is there a feature request open for this?
I found a satisfactory answer using declare. It's just I had to use declare var instead of declare function (which makes some sense):
type F = (_: number) => number;
declare var f:F;
function f(a) { return a; }
Using :F inline would be ideal, but this is good enough.
I'm trying the build a generic currying function that's look like:
package curry
import (
"fmt"
"reflect"
)
// Function
type fn interface{}
// Function parameter
type pr interface{}
// It return the curried function
func It(f fn, p ...pr) (fn, error) {
// examine the concret type of the function f
if reflect.ValueOf(f).Kind() == reflect.Func {
// Get the slice of input and output parameters type
} else {
return nil, fmt.Errorf("%s", "takes a function as a first parameter")
}
// _, _ = f, p
return nil, nil
}
Is it possible to extract the slice of input and output parameters types as []reflect.Type of the function f ?
You can use reflect.Type.In(int) and reflect.Type.Out(int), there are corresponding methods called NumIn() int and NumOut() int that give you the number of inputs/outputs.
However, keep in mind a few caveats:
To correctly extract the function for an arbitrary signature, you'll need an infinite number of cases. You'll have to switch over every single In and Out in turn to correctly get the type to extract.
You can't dynamically create a function anyway. There's no FuncOf method to go with SliceOf, MapOf, etc. You'll have to hand code the curried versions anyway.
Using reflection to emulate generics is generally considered a Bad Idea™.
If you absolutely have to do something like this, I'd heavily recommend making an interface and having each implementation do the currying itself, rather than trying to hack it "generically" for all cases, which will never work as of Go 1.2.1.
Go 1.5 will add a function that could help here.
(review 1996, commit e1c1fa2 by Dave (okdave))
// FuncOf returns the function type with the given argument and result types.
// For example if k represents int and e represents string,
// FuncOf([]Type{k}, []Type{e}, false) represents func(int) string.
//
// The variadic argument controls whether the function is variadic. FuncOf
// panics if the in[len(in)-1] does not represent a slice and variadic is
// true.
func FuncOf(in, out []Type, variadic bool) Type
The test cases include this intriguing code:
v := MakeFunc(FuncOf([]Type{TypeOf(K(""))}, []Type{TypeOf(V(0))}, false), fn)
outs := v.Call([]Value{ValueOf(K("gopher"))})