Live data from Hacker News

A Fairy Tale of F# and Durable Functions

hackernoon.com

11–20 of 32 posts

Re: A Fairy Tale of F# and Durable Functions

#11
post #8
post #7

Earlier quoted context omitted.

This is why I love Haskell. You can easily define your own "|>" operator: (|>) :: a -> (a -> b) -> b x |> f = apply x f

but nobody uses it because "function composition" reads the other way and tends to be preferable i.e. (g ∘ f)(x) = g (f(x)) // math (g . f) x = g (f x) // haskell g f x g f x // see how the g f x order always matches with the default application and composition notation. you can mess with the order and "turn the order of application "inside-out" but then you have to switch modes from left-to-right and right-to-left m…

    g f x 
would not be the same as

    (g . f) x
you need the right associative function application operator $, ie.

    g $ f x
or simply

    g (f x)

Re: A Fairy Tale of F# and Durable Functions

#12
post #2

Nice article. F# can be so readable, e.g.: // WishList -> Async let workflow (wishlist: WishList) = async { // 1. Find matches for each wish let! matches = wishlist.Wishes |> List.map findMatchingGift |> Async.Parallel // 2. Pick one product from the combined list of matches let gift = pickGift (List.concat matches) // 3. Register and return the reservation let reservation = { Kid = wishlist.Kid; Product = gift } do!…

I went through a phase where I tried making the entry point of each project or major module read like nothing more than: inputs |> step1 |> step2 |> step3 |> etc ... and it seemed mostly doable, although I would wind up needing a layer of parameter rearrangement functions to make it read quite that cleanly. I don't know if I have a concrete opinion on how it worked out - I suppose I need to get back into doing this s…

I've been wondering if there's any value in having a syntax for partial application that works more like:

  fun(arg1, _, arg3)
where the "_" indicates a skipped argument. My thought being that, in return for being a little bit more syntax-heavy, you'd get several potential advantages: No need for parameter rearrangement functions, easier overloading, and the more explicit syntax might help with maintainability.

Re: A Fairy Tale of F# and Durable Functions

#13
post #2

Nice article. F# can be so readable, e.g.: // WishList -> Async let workflow (wishlist: WishList) = async { // 1. Find matches for each wish let! matches = wishlist.Wishes |> List.map findMatchingGift |> Async.Parallel // 2. Pick one product from the combined list of matches let gift = pickGift (List.concat matches) // 3. Register and return the reservation let reservation = { Kid = wishlist.Kid; Product = gift } do!…

What I think is most interesting is that the thing that enables F# code to be so readable is exactly the thing that I thought would be its biggest readability problem when I first encountered it: The function call syntax and semantics. Specifically, the fact that there's no requirement to place any brackets around an invocation or its argument list, and the currying by default. But the same syntax is what makes parti…

I agree. The first time I saw F#, I was immediately concerned about single spaces without any braces/brackets/parens indicating function executions.

I stuck it out with F#, though, and now I miss that syntax greatly when I have to use other languages. It's surprisingly wonderful (at least in my opinion). Or at least in languages where partial application / currying / composition is easily-available. I suspect that syntax wouldn't be very helpful with languages where that isn't the case.

Re: A Fairy Tale of F# and Durable Functions

#14

Earlier quoted context omitted.

I went through a phase where I tried making the entry point of each project or major module read like nothing more than: inputs |> step1 |> step2 |> step3 |> etc ... and it seemed mostly doable, although I would wind up needing a layer of parameter rearrangement functions to make it read quite that cleanly. I don't know if I have a concrete opinion on how it worked out - I suppose I need to get back into doing this s…

I've been wondering if there's any value in having a syntax for partial application that works more like: fun(arg1, _, arg3) where the "_" indicates a skipped argument. My thought being that, in return for being a little bit more syntax-heavy, you'd get several potential advantages: No need for parameter rearrangement functions, easier overloading, and the more explicit syntax might help with maintainability.

Scala uses this syntax and I find it to be quite nice:

  (0 to 100).map(someFunc(arg1, arg2, _, arg3))

Re: A Fairy Tale of F# and Durable Functions

#15
post #2

Nice article. F# can be so readable, e.g.: // WishList -> Async let workflow (wishlist: WishList) = async { // 1. Find matches for each wish let! matches = wishlist.Wishes |> List.map findMatchingGift |> Async.Parallel // 2. Pick one product from the combined list of matches let gift = pickGift (List.concat matches) // 3. Register and return the reservation let reservation = { Kid = wishlist.Kid; Product = gift } do!…

I went through a phase where I tried making the entry point of each project or major module read like nothing more than: inputs |> step1 |> step2 |> step3 |> etc ... and it seemed mostly doable, although I would wind up needing a layer of parameter rearrangement functions to make it read quite that cleanly. I don't know if I have a concrete opinion on how it worked out - I suppose I need to get back into doing this s…

That can be fun and is only one step away from "point-free style". Just leave out the inputs altogether and switch to direct function composition:

    let myFunc = step1 >> step2 >> step3 >> etc
Personally, I often find point-free to be a little too terse, but occasionally it's much clearer than "regular" code.

https://en.wikipedia.org/wiki/Tacit_programming

Re: A Fairy Tale of F# and Durable Functions

#16
post #7

Earlier quoted context omitted.

I went through a phase where I tried making the entry point of each project or major module read like nothing more than: inputs |> step1 |> step2 |> step3 |> etc ... and it seemed mostly doable, although I would wind up needing a layer of parameter rearrangement functions to make it read quite that cleanly. I don't know if I have a concrete opinion on how it worked out - I suppose I need to get back into doing this s…

This is why I love Haskell. You can easily define your own "|>" operator: (|>) :: a -> (a -> b) -> b x |> f = apply x f

It feels so weird that I can understand this discussion now.

I used to think that all these Haskell discussions were garbage. But now I get it.

It's still very inaccessible, in my opinion. But I'm working on something to help change all that.

Re: A Fairy Tale of F# and Durable Functions

#17
post #8

Earlier quoted context omitted.

but nobody uses it because "function composition" reads the other way and tends to be preferable i.e. (g ∘ f)(x) = g (f(x)) // math (g . f) x = g (f x) // haskell g f x g f x // see how the g f x order always matches with the default application and composition notation. you can mess with the order and "turn the order of application "inside-out" but then you have to switch modes from left-to-right and right-to-left m…

g f x would not be the same as (g . f) x you need the right associative function application operator $, ie. g $ f x or simply g (f x)

i know that, i was just highlighting the appearance of the order of the letters without considering associativity.

Re: A Fairy Tale of F# and Durable Functions

#18
post #2

Nice article. F# can be so readable, e.g.: // WishList -> Async let workflow (wishlist: WishList) = async { // 1. Find matches for each wish let! matches = wishlist.Wishes |> List.map findMatchingGift |> Async.Parallel // 2. Pick one product from the combined list of matches let gift = pickGift (List.concat matches) // 3. Register and return the reservation let reservation = { Kid = wishlist.Kid; Product = gift } do!…

What I think is most interesting is that the thing that enables F# code to be so readable is exactly the thing that I thought would be its biggest readability problem when I first encountered it: The function call syntax and semantics. Specifically, the fact that there's no requirement to place any brackets around an invocation or its argument list, and the currying by default. But the same syntax is what makes parti…

I actually completely disagree about the explicit `do` blocks; as a consequence of that decision, you can't write functions that abstract over all monads, at least not easily. I like F#, but that has always been my main gripe for the two years that I did F# full-time.

I realize that for business code that that isn't a super big deal, but it becomes an issue if you want to write generic libraries; the closest thing that you can do is to exploit static-resolved types with member constraints and do explicit binds.

For example, if I wanted to have a monad transformer for Async, I could define the custom monad, but then I end up having to wrap every regular Async function manually (or do a lot of manual unboxing) to make it work. A lot of the time, my logic in the async blocks isn't specific to async, and I feel that when you're forced to write custom unboxing everywhere, that's a good way to make a lot of mistakes.

EDIT: Just an FYI, despite this complaint, I do really like F#...I find it an incredibly practical language, and one of the best of the Hindley-Milner-style functional languages.

Re: A Fairy Tale of F# and Durable Functions

#19
post #2

Nice article. F# can be so readable, e.g.: // WishList -> Async let workflow (wishlist: WishList) = async { // 1. Find matches for each wish let! matches = wishlist.Wishes |> List.map findMatchingGift |> Async.Parallel // 2. Pick one product from the combined list of matches let gift = pickGift (List.concat matches) // 3. Register and return the reservation let reservation = { Kid = wishlist.Kid; Product = gift } do!…

I don't know, from this I can't really see the memory cost or GC impact. And the parallel statement doesn't tell me anything of the threading model. I know that I see a lot of intermediate states being created which is not so good. If this code were shown to compile to the imperative equivalent though, I'd definitely think about learning F#.

Re: A Fairy Tale of F# and Durable Functions

#20
post #2

Nice article. F# can be so readable, e.g.: // WishList -> Async let workflow (wishlist: WishList) = async { // 1. Find matches for each wish let! matches = wishlist.Wishes |> List.map findMatchingGift |> Async.Parallel // 2. Pick one product from the combined list of matches let gift = pickGift (List.concat matches) // 3. Register and return the reservation let reservation = { Kid = wishlist.Kid; Product = gift } do!…

[deleted]
Post reply on HN