What if we define a |>! operator like so:
let (|>!) a f = async {
let! r = a
return f r
}
Then instead of writing
let! r = fetchAsync()
work r
we could write
fetchAsync() |>! work
Is this a good idea or would it generate inefficient code?
The |>! operator you're describing is the standard "map" pattern that can apply to just about any "wrapper" type, not just async. If your return f r had been return! f r then you would have the standard "bind" pattern, which by convention should be written as the operator >>= if you're defining an operator for it.
And it is a good idea, but with one minor change. You've written it with the async value as the first parameter and the function as the second parameter, but the way you used it, fetchAsync() |>! work, requires the function to be the first parameter, e.g. let (|>!) f a = .... (If you look at the way Scott Wlaschin implements this in the first example I linked, he puts the function as the first parameter as well.) Also, I think most F# programmers would choose not to write this as an operator, but as a function called Async.map, so that its usage would look like this:
let result =
fetchAsync()
|> Async.map step1
|> Async.map step2
|> Async.map step3
Related
I'm trying to learn F# at the moment and have come up on a problem I can't solve and can't find any answers for on google.
Initially I wanted a log function that would work like the printf family of functions whereby I could provide a format string and a number of arguments (statically checked) but which would add a little metadata before printing it out. With googling, I found this was possible using a function like the following:
let LogToConsole level (format:Printf.TextWriterFormat<'T>) =
let extendedFormat = (Printf.TextWriterFormat<string->string->'T> ("%s %s: " + format.Value))
let date = DateTime.UtcNow.ToString "yyyy-MM-dd HH:mm:ss.fff"
let lvl = string level
printfn extendedFormat date lvl
having the printfn function as the last line of this function allows the varargs-like magic of the printf syntax whereby the partially-applied printfn method is returned to allow the caller to finish applying arguments.
However, if I have multiple such functions with the same signature, say LogToConsole, LogToFile and others, how could I write a function that would call them all keeping this partial-application magic?
Essential I'm looking for how I could implement a function MultiLog
that would allow me to call multiple printf-like functions from a single function call Such as in the ResultIWant function below:
type LogFunction<'T> = LogLevel -> Printf.TextWriterFormat<'T> -> 'T
let MultiLog<'T> (loggers:LogFunction<'T>[]) level (format:Printf.TextWriterFormat<'T>) :'T =
loggers
|> Seq.map (fun f -> f level format)
|> ?????????
let TheResultIWant =
let MyLog = MultiLog [LogToConsole; LogToFile]
MyLog INFO "Text written to %i outputs" 2
Perhaps the essence of this question can be caught more succintly: given a list of functions of the same signature how can I partially apply them all with the same arguments?
type ThreeArg = string -> int -> bool -> unit
let funcs: ThreeArg seq = [func1; func2; func3]
let MagicFunction = ?????
// I'd like this to be valid
let partiallyApplied = MagicFunction funcs "string"
// I'd also like this to be valid
let partiallyApplied = MagicFunction funcs "string" 255
// and this (fullyApplied will be `unit`)
let fullyApplied = MagicFunction funcs "string" 255 true
To answer the specific part of the question regarding string formatting, there is a useful function Printf.kprintf which lets you do what you need in a very simple way - the first parameter of the function is a continuation that gets called with the formatted string as an argument. In this continuation, you can just take the formatted string and write it to all the loggers you want. Here is a basic example:
let Loggers = [printfn "%s"]
let LogEverywhere level format =
Printf.kprintf (fun s ->
let date = DateTime.UtcNow.ToString "yyyy-MM-dd HH:mm:ss.fff"
let lvl = string level
for logger in Loggers do logger (sprintf "%s %s %s" date lvl s)) format
LogEverywhere "BAD" "hi %d" 42
I don't think there is a nice and simple way to do what you wanted to do in the more general case - I suspect you might be able to use some reflection or static member constraints magic, but fortunately, you don't need to in this case!
There is almost nothing to add to a perfect #TomasPetricek answer as he is basically a "semi-god" in F#. Another alternative, which comes to mind, is to use a computation expression (see, for example: https://fsharpforfunandprofit.com/series/computation-expressions.html). When used properly it does look like magic :) However, I have a feeling that it is a little bit too heavy for the problem, which you described.
When the following is submitted to the compiler
fn main()
{
let abc = vec![10u, 20u, 30u];
let bcd = vec![20u, 30u, 40u];
let cde = abc.append(bcd.as_slice());
println!("{}", cde);
}
the compiler emits the following warning:
this function has been deprecated in favor of extend()
How would the equivalent look using extend?
Take a look at the signature for extend:
fn extend<I: Iterator<T>>(&mut self, iterator: I)
Note that it takes self by a mutable reference, and that it doesn’t take a slice but rather an iterator (which is more general-purpose).
The end result would look like this, then:
abc.extend(bcd.into_iter());
Or this:
abc.extend(bcd.iter().map(|&i| i))
(Bearing in mind that Vec.iter() produces something that iterates over references rather than values, hence the need for .map(|&i| i).)
I am a little surprised that it is recommending extend, as push_all is a much more direct replacement, taking a slice rather than an iterator:
abc.push_all(bcd.as_slice());
(Really strugging to title this question, so if anyone has suggestions feel free.)
Say I wanted to do an operation like:
take an array [1,2,3]
multiply each element by 2 (map): [2,4,6]
add the elements together (reduce): 12
multiply the result by 10: 120
I can do this pretty cleanly in underscore using chaining, like so:
arr = [1,2,3]
map = (el) -> 2*el
reduce = (s,n) -> s+n
out = (r) -> 10*r
reduced = _.chain(arr).map(map).reduce(reduce).value()
result = out(reduced)
However, it would be even nicer if I could chain the 'out' method too, like this:
result = _.chain(arr).map(map).reduce(reduce).out(out).value()
Now this would be a fairly simple addition to a library like underscore. But my questions are:
Does this 'out' method have a name in functional programming?
Does this already exist in underscore (tap comes close, but not quite).
This question got me quite hooked. Here are some of my thoughts.
It feels like using underscore.js in 'chain() mode' breaks away from functional programming paradigm. Basically, instead of calling functions on functions, you're calling methods of an instance of a wrapper object in an OOP way.
I am using underscore's chain() myself here and there, but this question made me think. What if it's better to simply create more meaningful functions that can then be called in a sequence without having to use chain() at all. Your example would then look something like this:
arr = [1,2,3]
double = (arr) -> _.map(arr, (el) -> 2 * el)
sum = (arr) -> _.reduce(arr, (s, n) -> s + n)
out = (r) -> 10 * r
result = out sum double arr
# probably a less ambiguous way to do it would be
result = out(sum(double arr))
Looking at real functional programming languages (as in .. much more functional than JavaScript), it seems you could do exactly the same thing there in an even simpler manner. Here is the same program written in Standard ML. Notice how calling map with only one argument returns another function. There is no need to wrap this map in another function like we did in JavaScript.
val arr = [1,2,3];
val double = map (fn x => 2*x);
val sum = foldl (fn (a,b) => a+b) 0;
val out = fn r => 10*r;
val result = out(sum(double arr))
Standard ML also lets you create operators which means we can make a little 'chain' operator that can be used to call those functions in a more intuitive order.
infix 1 |>;
fun x |> f = f x;
val result = arr |> double |> sum |> out
I also think that this underscore.js chaining has something similar to monads in functional programming, but I don't know much about those. Though, I have feeling that this kind of data manipulation pipeline is not something you would typically use monads for.
I hope someone with more functional programming experience can chip in and correct me if I'm wrong on any of the points above.
UPDATE
Getting slightly off topic, but one way to creating partial functions could be the following:
// extend underscore with partialr function
_.mixin({
partialr: function (fn, context) {
var args = Array.prototype.slice.call(arguments, 2);
return function () {
return fn.apply(context, Array.prototype.slice.call(arguments).concat(args));
};
}
});
This function can now be used to create a partial function from any underscore function, because most of them take the input data as the first argument. For example, the sum function can now be created like
var sum = _.partialr(_.reduce, this, function (s, n) { return s + n; });
sum([1,2,3]);
I still prefer arr |> double |> sum |> out over out(sum(double(arr))) though. Underscore's chain() is nice in that it reads in a more natural order.
In terms of the name you are looking for, I think what you are trying to do is just a form of function application: you have an underscore object and you want to apply a function to its value. In underscore, you can define it like this:
_.mixin({
app: function(v, f) { return f (v); }
});
then you can pretty much do what you asked for:
var arr = [1,2,3];
function m(el) { return 2*el; };
function r(s,n) { return s+n; };
function out(r) { return 10*r; };
console.log("result: " + _.chain(arr).map(m).reduce(r).app(out).value()));
Having said all that, I think using traditional typed functional languages like SML make this kind of think a lot slicker and give much lighter weight syntax for function composition. Underscore is doing a kind of jquery twist on functional programming that I'm not sure what I think of; but without static-type checking it is frustratingly easy to make errors!
If I have a function that takes in another function:
[<SomeAttribute()>]
let f (g:unit->unit) =
//Want to get g's custom attributes
How can I access g's custom attributes from f?
I think I'm missing something really obvious here.
This is not in general possible, because when you use a function as an argument (e.g. f foo), the F# compiler wraps the foo value into some object. Extracting the actual method reference foo from this object would be very difficult (and it would work only if the compiler didn't do some optimizations).
However, you can get the desired behavior using F# quotations. Instead of taking a function unit -> unit, your f can take a quoted function Expr<unit -> unit>. You can then call the function using f <# foo #> and the function can extract the method refernce and also call foo.
Here is an example. It requires reference to F# PowerPack (so that it can evaluate the quotation). In this simple case, the evaluation should be quite efficient:
#r #"FSharp.PowerPack.Linq.dll"
type SomeAttribute(name:string) =
inherit System.Attribute()
member x.Name = name
// Example function with some attribute
[<SomeAttribute("Test")>]
let g () = printfn "Hello"
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Linq.QuotationEvaluation
// Takes a quotation instead of a function value
let f (g:Expr<unit->unit>) =
// Extract method info & attributes from the quotation
match g with
| DerivedPatterns.Lambdas(_, Patterns.Call(_, mi, _)) ->
let attrs = mi.GetCustomAttributes(typeof<SomeAttribute>, false)
for a in attrs |> Seq.cast<SomeAttribute> do
printfn "%A" a.Name
| _ ->
failwith "Argument must be of the form <# foo #>!"
// Compile the function so that it can be executed (the compilation
// takes some time, but calling invoke should be fast)
let invoke = g.Compile()()
invoke()
invoke()
// And this is how you call the function
f <# g #>
let f (g:unit->unit) =
printfn "%d" (g.GetType().GetCustomAttributes(true).Count())
For some reason, I tend to associate closures with functional languages. I believe this is mostly because the discussions I've seen concerning closures is almost always in an environment that is focused around functional programming. That being said, the actual practical uses of closures that I can think are are all non-functional in nature.
Are there practical uses of closures in functional languages, or is the association in my mind mostly because closures are used to program in a style that's also common to functional programming languages (first class functions, currying, etc)?
Edit: I should clarify that I refering to actual functional languages, meaning I was looking for uses that preserve referential transparency (for the same input you get the same output).
Edit: Adding a summary of what's been posted so far:
Closures are used to implement partial evaluation. Specifically, for a function that takes two arguments, it can be called with one argument which results in it returning a function that takes one argument. Generally, the method by which this second function "stores" the first value passed into it is a closure.
Objects can be implemented using closures. A function is returned that has closes around a number of variables, and can then use them like object attributes. The function itself may return more methods, which act as object methods, which also have access to these variables. Assuming the variables aren't modified, referential transparency is maintained.
I use lots of closures in Javascript code (which is a pretty functional language -- I joke that it is Scheme with C clothing). They provide encapsulation of data that is private to a function.
The most ubiquitous example:
var generateId = function() {
var id = 0;
return function() {
return id++;
}
}();
window.alert(generateId());
window.alert(generateId());
But that's the hello, world of Javascript closures. However there are many more practical uses.
Recently, in my job, I needed to code a simple photo gallery with sliders. It does something like:
var slide = function() {
var photoSize = ...
var ... // lots of calculations of sizes, distances to scroll, etc
var scroll = function(direction, amout) {
// here we use some of the variables defined just above
// (it will be returned, therefore it is a closure)
};
return {
up: function() { scroll(1, photoSize); },
down: function() { scroll(-1, photoSize); }
}
}();
slide.up();
// actually the line above would have to be associated to some
// event handler to be useful
In this case I've used closures to hide all the up and down scrolling logic, and have a code which is very semantic: in Javascript, "slide up" you will write slide.up().
One nice use for closures is building things like decision trees. You return a classify() function that tests whether to go down the left or right tree, and then calls either its leftClassify() or rightClassify() function depending on the input data. The leaf functions simply return a class label. I've actually implemented decision trees in Python and D this way before.
They're used for a lot of things. Take, for example, function composition:
let compose f g = fun x -> f (g x)
This returns a closure that uses the arguments from the function environment where it was created. Functional languages like OCaml and Haskell actually use closures implicitly all over the place. For example:
let flip f a b = f b a
Usually, this will be called as something like let minusOne = flip (-) 1 to create a function that will subtract 1 from its argument. This "partially applied" function is effectively the same as doing this:
let flip f a = fun b -> f b a
It returns a closure that remembers the two arguments you passed in and takes another argument of its own.
Closures can be used to simulate objects that can respond to messages and maintain their own local state. Here is a simple counter object in Scheme:
;; counter.ss
;; A simple counter that can respond to the messages
;; 'next and 'reset.
(define (create-counter start-from)
(let ((value start-from))
(lambda (message)
(case message
((next) (set! value (add1 value)) value)
((reset) (set! value start-from))
(else (error "Invalid message!"))))))
Sample usage:
> (load "counter.ss")
> (define count-from-5 (create-counter 5))
> (define count-from-0 (create-counter 0))
> (count-from-5 'next)
6
> (count-from-5 'next)
7
> (count-from-0 'next)
1
> (count-from-0 'next)
2
> (count-from-0 'reset)
> (count-from-0 'next)
1