DEV Community

Discussion on: Impeachment in a functional way

Collapse
 
shimmer profile image
Brian Berns • Edited

Kleisli composition! :)

It's great to see another F# developer here. I learned something new from your code when I saw the fish operator defined as an infix function that takes three arguments. I didn't even know that was possible. I guess F# knows that the >=> always goes between the first two arguments? I found it a little easier to understand when I rewrote mentally it as:

let (>=>) a b =
    fun x ->
        match a x with
        | Impeach v -> b v
        | DontImpeach reason -> DontImpeach(reason)
Enter fullscreen mode Exit fullscreen mode

Your version is shorter and cleaner, though, so I certainly don't object.

The other thought I had is a minor suggestion. Functions that match on their last argument are a pretty common pattern in F#, so there's a bit of syntactical sugar you can use if you want to tighten them up. Instead of this:

let tryInSenate exitAt =
    match exitAt with
    | Trial -> DontImpeach (Reason "Senate trial exonerated the President")
    | _ -> Impeach exitAt
Enter fullscreen mode Exit fullscreen mode

You can write:

let tryInSenate = function
    | Trial -> DontImpeach (Reason "Senate trial exonerated the President")
    | exitAt -> Impeach exitAt
Enter fullscreen mode Exit fullscreen mode

Of course, the downside to this approach is that the argument disappears entirely ("point-free" style), which can make the code harder to understand. Just wanted to mention it as an idea.

Lastly, on a purely humorous note, since you're concerned about the bias of using the Result type, you missed a great opportunity to use a Haskell-style Either type instead, since its constructors are Left and Right!

Collapse
 
t4rzsan profile image
Jakob Christensen • Edited

Thank you for your reply. You made my day for suggesting Either 🤣🤣🤣. Now I feel like rewriting the whole thing with Left and Right.

I use Wlaschin's syntax for >=> while Milewski writes it like you do in his section on Kleisli categories (although in Haskell). The two implementations must be equal because of partial application (?). In a way I actually like your way better because it is very clear that the operator returns a function.

I hardly ever use point free-free programming since it makes debugging so much harder. Microsoft has a couple of guidelines on that.

Calling me an F#-developer is a bit of a stretch though and I am still learning. None of my colleagues have seen the light and they all use C#. So I am yet to write a complete project in F# which is such a shame.

Thanks for reading! I look forward to reading your articles on F#!

Collapse
 
shimmer profile image
Brian Berns • Edited

I tend to agree with you (and Microsoft) about point-free style, although there are some cases where it's absolutely essential (e.g. parser combinators). I even wrote a blog post about this here. However, in the function case, the compiler desugars it back to your original code with an argument called _arg1, so it can be easily inspected in a debugger.

I hope you keep going in your F# journey. I was/am in a similar situation, although I've at least convinced my colleagues to allow a few of my F# projects side-by-side with their C# projects. Thanks to .NET, they interop without problems.

Thread Thread
 
t4rzsan profile image
Jakob Christensen

Thanks for the tip on point-free style.

I have been mixing C# and F# projects in the same solution as well and the interop works perfectly as you say but I find the tooling support to be troublesome. If you use "Find all references" or "Go to definition" in Visual Studio I cannot get it to work across different project types. Did you find a solution for that?

Thread Thread
 
shimmer profile image
Brian Berns

I've had the same experience. Tooling support is definitely not perfect, but Visual Studio is still the best IDE out there, I think.

Thread Thread
 
t4rzsan profile image
Jakob Christensen

VS is definitely the best. I have been doing some macOS/iOS stuff lately and XCode is a pain compared to VS.