DEV Community

[Comment from a deleted post]
 
jon49 profile image
Jon Nyman

Yes, you do take care of it at the end, since normally you are doing the same flow every time in code. Like if there is a database error you might return a status code of 500 and log the error. And in F# the error return is a union (algebraic) data type. So, you might have these known return types:

type Errors =
  | DbError of string
  | NotFound of string
  | ... of ...

And then at the end you check against every error type with the same function for all your end points.

let checkErrors context result =
  match result with
  | DbError myString ->
    context.HttpStatusCode <- HttpStatusCode.ServerError
    context.Body <- """<p class="error">Oops - Something went wrong try again</p>"""
    context
  | NotFound mySearchValue ->
    context.HttpStatusCode <- HttpStatusCode.NotFound
    context.Body <- sprintf """<p class="warning">Could not find %s.</p>""" mySearchValue

And this is what the code might look like before then:

result {
// ...
} |> okResult

Where OkResult would be something like this:

let okResult result =
  match result with
  | Ok html ->
     // return whatever html code here
  | Error error ->
     // match against error types with the code mentioned above.

Of course, if you have some custom logic in your code where you might want to check your errors before you can do that. And all your code with give compile time errors if you don't match against everything unless you use the general escape clause (otherwise). But I typically like to keep everything the same and uniform, which makes programming easier since I know beforehand what I'll be getting back in most cases. But if I ever need to deviate it isn't a huge deal. And if I ever decide to change something it is in one central location.

I just kept all of that out just to keep it simple. Also, I'm not trying to get into a language war or anything. Just showing that simple abstractions can make code easier to read and write and help keep everything uniform and make it easy to change things up if you ever decide to return something different.

I like some of the things you mentioned about Go, like it compiling to a single file and fast compilation (F# can be a bit slow, unfortunately - mainly because there aren't enough people working on the core product to speed it up).

What I like about F# is Type Providers (I have static typing all the way from my database and other external sources). White space language (I know a lot of people don't like that but I think I got my coding chops originally in VB so I learned to hate curly braces and semicolons - everyone writes their code with white space anyways why not let the compiler do the computers work rather than me having to insert all the semicolons and curly braces?), Computation expressions where I can create DSLs so the intent of the code is more clear. People seem to be able to write accurate bug free code in a short amount of time - despite F#s small community a lot of work is created in a short amount of time.

 
jon49 profile image
Jon Nyman

Just one last thing. I can see why we gravitate towards the different language ecosystems. You come from the C world and I come from the .NET world. So, it is much easier for you to make the leap towards Go and it is much easier for me to make the leap towards F#. Especially now that I have kids which really limits my time.

One thing that I did want to learn is PostgresQL. But the leap from SQL Server to PostgreQL is pretty high for me. Partly because the tooling around SQL Server makes the tooling around Postgres look rather primitive. I use SQL Server Data Tools which makes writing tables/stored procs/inline table valued functions/etc all declarative and it can do diffs against the database and gives me great intellisense. I believe there are tools out there for diffs with Postgres but they are rather rudimentary and the IDE for Postgres is also pretty rudimentary from what I tried. When I tried the IDE for Postgres it couldn't even differentiate between the columns of a joined table. But I always wonder if I am approaching it wrong of it there is some tool that I didn't find that works better or if there is something that I was doing wrong. I know Postgres has built in language parsers that can make the tooling just as powerful as SQL Server. I imagine if I knew someone that programmed with Postgres then the leap would be much easier.

Sorry, I'm just rambling. I'm looking forward to any other work you put out about this. It is all so fascinating!