[HN Gopher] What I wish I knew when learning F#
___________________________________________________________________
What I wish I knew when learning F#
Author : DeathArrow
Score : 206 points
Date : 2021-10-14 12:07 UTC (10 hours ago)
(HTM) web link (danielbachler.de)
(TXT) w3m dump (danielbachler.de)
| Multicomp wrote:
| I am building a tabletop game trainer for Star Wars FFG as the
| RPG Sessions app is incomplete and trying to do all of the things
| manually or remember every rule + every modifier to the rule +
| what all of my NPCs stats are is impossible, and thus when one
| looks things up, it slows down gameplay a lot, especially during
| battles. Since the whole point of the system is to make battles
| feel fast and cinematic, and we want to strictly adhere to the
| rules as written so we are not constantly re-adjudicating (read:
| bickering over) house rules, we need something more.
|
| Enter F#. I've been working on (yet not releasing a usable
| version yet bc I'm bad) this program entirely in F#, using
| Giraffe as the web layer, following the general architecture
| defined in Domain Modelling Made Functional, and using Dapper to
| write to a Sqlite database.
|
| F# is amazing. I'm able to fully understand the codebase and
| follow exactly what happens from HTML Form request, through input
| validation, through the business logic, down to the database and
| back to the domain, then rendering out to a JS-free webpage via
| Giraffe.
|
| It gets tedious doing the marshalling/unmarshalling from HTML
| form to input DTO to domain type to output DTO to database
| records to input DTO etc. and I need to learn both how to create
| DSLs (so users can type in rules from the book and the system
| will extract the keywords and compose them into the closest
| equivalent set of conditions and effects the system supports) and
| lock down my bounded contexts so I'm developing them in order of
| least to most entity dependencies rather than in order of where I
| feel I need them most, but I can't see a way where I would be
| able to build this in plain old C# without all of my above
| challenges + lots of boilerplate code to ensure my expected
| invariants are met and someone (me) hasn't changed an invariant
| out from under me somewhere else without realizing it.
| 2mol wrote:
| Yeah, those boundaries between beautiful domain type <-> DTO
| <-> database is also something my team and I struggle with. In
| the end we're happy with just writing it out, but there is this
| nagging feeling that it could be more ergonomic.
|
| I'd be interested to hear about other approaches. You could in
| theory just dump (automatically generated) JSON to the database
| and evolve your types with tagged versions, but then you have
| to write some boilerplatey converters between TypeV1, TypeV2,
| TypeV3, ...
|
| I guess that's the price for staying away from full-blown ORMs?
|
| It reminds me a bit of how in Elm you just suck it up and write
| the JSON en-/decoders by hand. Annoying at first, but then you
| get super obvious and maintainable code out of it, which is
| quite a joy.
| iudqnolq wrote:
| I kind of like the Elixir Ecto approach where your "DTO"s are
| mostly plain old data with a single hidden attribute
| identifying the database table and some other db metadata.
| They're not live/active, you have to manually pass them to
| functions to update, but you avoid having two nearly
| identical types.
| de_keyboard wrote:
| > It reminds me a bit of how in Elm you just suck it up and
| write the JSON en-/decoders by hand. Annoying at first, but
| then you get super obvious and maintainable code out of it,
| which is quite a joy.
|
| The F# take on Elm coders (Thoth.Json) can use reflection to
| generate them automatically. This is really useful at the
| prototyping stage.
| 2mol wrote:
| Yup, I love Thoth. At work we just use System.Text.Json +
| FSharp.SystemTextJson though, that also generates
| (de)serializers, and it has a bunch of options to fine-tune
| naming conventions, sum type encoding, etc. Super useful
| and easy to hammer out the correct type for very big and
| nested JSONs.
| chalst wrote:
| The main thing I found strange about F# was that, having prior
| familiarity with Ocaml and SML/NJ, was that what F# calls modules
| are completely unlike the module system of any other ML-inspired
| language, being instead an adaption of C# classes to serve F#'s
| namespacing needs. Since the module system is of similar
| importance to code reuse to Haskell's typeclasses,the relative
| deficiencies of F#'s module system hurt.
| infogulch wrote:
| There was a recent thread about Algebraic Effects in OCaml [0].
| Does F# have something similar?
|
| [0]: https://news.ycombinator.com/item?id=28838099
| Smaug123 wrote:
| No. It has lightweight syntax ("computation expressions") you
| can use to sugar monads, but no effects system.
| xvilka wrote:
| It lacks many things that OCaml has. On the other hands, units
| support is awesome, I wish there would have been more attention
| to that, and more popular in other languages as well.
| muglug wrote:
| > It has a scripting mode where compilation is done on the fly.
| This makes it look and feel very similar to python but you still
| get type checking and much better performance.
|
| This is a really wonderful quality in a compiled language. I wish
| there were more languages with this attribute (but it's a lot to
| ask for).
| BBC-vs-neolibs wrote:
| Crystal, the compiled-but-super-fast statically typed _Ruby_
| dialect.
| eatonphil wrote:
| I've had good experiences running F# on Linux. I used it to build
| an API generator from database schemas [0]. Similar to Go you can
| get a single static binary you can copy anywhere.
|
| It's very convenient and you've got a massive number of .NET APIs
| to fall back on.
|
| The language is a little complex though. That you cannot call
| interface methods on an object implementing the interface without
| explicitly casting to the interface [1] is pretty weird. And
| getters/setters are a little complex.
|
| If you want an easy introduction to the ML family for
| educational/historic sake I'd always recommend Standard ML. But
| if you want a highly pragmatic, mature, strictly typed, compiled,
| cross-platform language F# is pretty compelling.
|
| [0] https://github.com/eatonphil/dbcore
|
| [1] https://docs.microsoft.com/en-us/dotnet/fsharp/language-
| refe...
| beecafe wrote:
| at least they picked cute bird face emoji for it :>
| nextos wrote:
| It's also important to add F# is an inspiration for an amazing
| MS Research effort, F* [1].
|
| Furthermore, it is also worth checking Dafny [2] (Spec#'s
| successor). The relationship between Dafny and C# is equivalent
| to the relationship between F* and F#. Both languages try to
| refine their predecessors semantics and augment them with
| practical constructs to prove program correctness.
|
| Some of the largest software artifacts ever verified have been
| implemented in Dafny [3], and F* is also looking quite
| promising.
|
| [1] https://www.fstar-lang.org
|
| [2] https://dafny-lang.github.io/dafny/
|
| [3]
| https://www.cs.columbia.edu/~junfeng/17sp-e6121/papers/ironf...
| phillipcarter wrote:
| The language, in general, wants you to be explicit about what
| you're working with. So implicit access to interface members
| isn't a thing, you need to say that "x is this interface type"
| or cast.
|
| In F# 6 things are changing a bit, and may possibly change in
| the future. There are various classes of cases where the type
| information is known, but the compiler still required you to
| explicitly cast things to be happy. That's no longer case. This
| link[0] has 3 examples that don't compile with F# 5 but will
| compile with F# 6.
|
| [0]
| https://sharplab.io/#v2:DYLgZgzgNALiBOBXAdgHwPToAQFMAeAhgLYA...
| Dayshine wrote:
| Implicit upcast? That's amazing, I feel like that's going to
| help a lot with many branched functions.
| phillipcarter wrote:
| Yeah, it's a good feature. It's been done carefully --
| there's room to do more of this kind of upcast conversion
| in the future -- but there's also a danger of creating code
| that behaves weirdly, too. See here for some of the dangers
| in Scala 2: https://latkin.org/blog/2017/05/02/when-the-
| scala-compiler-d...
| TravHatesMe wrote:
| > implicit access to interface members isn't a thing, you
| need to say that "x is this interface type" or cast.
|
| If the compiler already knows that it implements interface X
| Y and Z, it seems unnecessary to require it (unless those
| interfaces have conflicting names, in which case you would
| have to be explicit due to ambiguity).
|
| I feel like many languages are walking away from being so
| explicit, in particular I've noticed C# becoming more
| implicit over the years.
| bob1029 wrote:
| If you want to dabble in functional, C# is actually a compelling
| option now. Switch expressions and LINQ can take you a long way.
|
| I strongly believe that functional programming is not a good fit
| for 100% of software architecture. The best is some sort of
| hybrid. Generally, the closer you get to the business logic, the
| more functional you would want to be. The serializers, http
| servers, etc. are probably not worth the squeeze to force into a
| functional domain.
| enricosada wrote:
| C# switch are just syntactic sugar. nice for sure.
|
| But if you compare F# with C#, is not just LINQ .Select vs
| List.map
|
| And i am not speaking about function, who is just a part of why
| i like F#, not the best one
|
| Is the different defaults who matter, who guide you to an
| easier code who highlight the domain
|
| - structural comparison vs reference comparison - expression vs
| statement based - immutability
|
| C# will catchup with some features for sure.
|
| Lot of new C# feature remove boilerplate (file scoped
| namespace, etc) and is a good trend
|
| But the core defaults will be the same.
|
| That will not push to a single direction (if fact you have LOTS
| of way to write the thing in C#) while F# try to push to the
| same way
|
| To do so, C# continue to add thing to the LANGUAGE. Now is a
| lot more complicated than .NET 2.0
|
| While F# try to do the same, but the language doesnt change.
|
| An example: the async/task.
|
| C# added the async as keyword, plus all needed to make it work,
| and the compiler generate special code.
|
| F# has built that from the general computation expression
| feature and (recently) the state machine support.
| wyager wrote:
| > The serializers, http servers, etc. are probably not worth
| the squeeze to force into a functional domain.
|
| These are two examples I would probably come up with if you
| asked me "where does FP thoroughly beat imperative?"
|
| (De)Serializers - parser combinator libraries like attoparsec
| absolutely BTFO imperative parser libraries in most dimensions.
| Bidirectional codec libraries like haskell's Binary, Serial,
| Aeson[1] are top-tier. Functional formatters like Blaze are
| top-tier as well.
|
| Haskell's HTTP ecosystem is massively better than anything else
| I've used, and I went on a binge of trying a ton of HTTP
| servers like 6 years ago (in python, ruby, C++, Go, and finally
| Haskell).
|
| [1] https://github.com/lovasoa/bad_json_parsers
| JoelMcCracken wrote:
| I initially believed this, but I have come to realize that pure
| functional programming is transformative for both business
| logic and infrastructure. Its a lot easier to get started in
| the business logic side; dealing with effects in the context of
| pure functions is a lot to figure out, I don't even know if you
| really _can_ do it in not-haskell. But, via Haskell I have been
| able to achieve far greater levels of producitivty in these
| tasks than ever before.
|
| The main downside is that its a lot to learn, and it takes a
| good while before you get productive. But I am absolutely more
| productive now in Haskell than just about anything else, save
| perhaps ad-hoc text munging task; the shell DSL is just so
| handy for random one off stuff.
| Koshkin wrote:
| Sure - C# is the best functional language, while Haskell has
| already been the best imperative language for a while now [0].
|
| [0] https://stackoverflow.com/questions/6622524/why-is-
| haskell-s...
| GuuD wrote:
| I would have to respectfully disagree with you on the
| serializers part here. For me, after decades of fighting with
| "magic" stuff, simplicity is the key feature. So, everything
| that is a simple map function in disguise I tend to stick with
| functional languages and approaches.
| kevinmgranger wrote:
| I think it's really hard to properly define "functional
| programming" concretely, but I'll partially agree. If all a
| language takes from FP is:
|
| - make composition ergonomic, idiomatic, and easy (including
| the usual iterator map/reduce, etc.)
|
| - let the type system protect you (including nullability)
|
| Then you've already got the most important strengths, in my
| opinion.
| grumpyprole wrote:
| Functional programming is not just programming with closures.
| It's about "referential transparency". Referential
| transparency permits higher-level mathematical reasoning,
| which leads to safer/better program composition,
| optimisations, caching/reuse and parallelisation/concurrency.
| If you are willing to concede mutable-state and other
| uncontrolled effects, there is much to be gained.
| dboreham wrote:
| Citation needed.
|
| <ducks>
| mumblemumble wrote:
| I agree that 100% functional is not necessarily the way to go.
| That said, I am a _big_ fan of F# 's "functional first" ethos,
| which drives you toward that sweet spot of a functional core
| inside of an imperative shell.
|
| With C#, when I'm trying to use functional design, I often feel
| like I'm swimming against the current. The language has
| functional features, and it will certainly let you use them,
| but, LINQ aside, the path of least resistance is mostly
| imperative and object-oriented.
|
| In F#, it's the other way around. It has a full suite of
| object-oriented features - still, after all these years, quite
| a bit more complete than C#'s suite of functional features -
| but the path of least resistance is mostly functional.
|
| I don't want to say that's a universal best way to have things.
| But it suits my taste, because it makes the easiest way to do
| things correspond very closely with the way I like to see
| things done: distinct and well-distinguished layers of
| functional and object-oriented code, sorted according to where
| each is of the most utility. C#, by contrast, tends to guide
| you toward a foamy lather of functional and object-oriented
| code with no identifiable organizing principle.
| barrenko wrote:
| This is the same issue I have with Javascript. If you _don
| 't_ have to use something, you just won't, or maybe I'm just
| lazy.
| ulucs wrote:
| I think serializers would be better off as railways, allowing
| you to combine small serializers while also collecting the
| errors so you end up with a conclusive outcome. Haskell's
| parser combinators are quite fun for example.
|
| Also I've only used node/elixir serverside, but aren't http
| servers just a huge pipeline? It fits quite well into
| functional programming.
| bob1029 wrote:
| > aren't http servers just a huge pipeline
|
| Absolutely. At a certain level of abstraction they can be
| viewed in this way.
|
| How do HTTP servers actually get packets to and from the
| machine? At some point you have to interact with the
| operating system. This is not a realm where functional
| programming is very feasible today.
| de_keyboard wrote:
| > The serializers, http servers, etc. are probably not worth
| the squeeze to force into a functional domain.
|
| I used to think the same, but having now tried FP-style
| libraries for serializers (Thoth.Json) and HTTP servers
| (Suave), I think they are far superior to imperative or OOP
| alternatives. The ability to design these things in a
| declarative style makes the code much more robust _and_ easier
| to read.
| JaggerJo wrote:
| +1
| dustingetz wrote:
| FP is better on a 30 year timeframe but on a next-quarter
| timeframe probably still has not "crossed the chasm" - you
| need not just something accessible like ZIO but you need to
| figure out what it's killer app is, which the FP community
| currently doesn't have a clue. "HTTP server but more
| declarative and made with monads" is not something people
| cannot live without
| de_keyboard wrote:
| I think this depends on the relative weights you assign to
| learning a new language and program correctness.
| ghostwriter wrote:
| > I strongly believe that functional programming is not a good
| fit for 100% of software architecture. The best is some sort of
| hybrid.
|
| Haskell would be a better language in every domain where C# is
| applicable. That is from a language perspective, abundance of
| libraries is a different question, as it's a matter of the
| community size and attention.
| dboreham wrote:
| I think enforced purity is problematic (although obviously
| useful for some purposes such as program correctness proofs).
| I still want to be able to write:
|
| doThing1();
|
| // thing1 has finished
|
| doThing2();
|
| Where the functions block. Async and Monads and Futures and
| all are useful for some things, but mostly I just want to do
| stuff sequentially, blocking, and not confuse myself.
|
| Scala allows this, although the widespread Future-ification
| of libraries makes it hard to actually practice.
| ghostwriter wrote:
| Haskell allows this too, users can just code everything
| within IO until they feel comfortable with adding extra
| purity through refactoring: main :: IO ()
| main = do myBusinessLogic
| myBusinessLogic :: IO () myBusinessLogic = do
| doThing1 doThing2 doThing1 :: IO
| () doThing1 = do putStr "Hello "
| doThing2 :: IO () doThing2 = do
| putStrLn "World" --- ghc -o main
| main.hs [1 of 1] Compiling Main (
| main.hs, main.o ) Linking main ... ./main
| Hello World
| dboreham wrote:
| True. Perhaps my issue is that I know how that's
| implemented and my brain can't see it the same as
| sequential statement execution ;)
| JoelMcCracken wrote:
| This is a function of familiarity though. Get familiar
| with it and you'll understand it just fine.
|
| If you want to talk more about it, feel free to email me.
| tome wrote:
| I think dboreham's objection was exactly the opposite!
| JoelMcCracken wrote:
| Idk i mean simply knowing what the code for >> looks like
| doesn't mean you're used to thinking in that way.
|
| There was a time years ago when someone was showing me
| the types of (>>) and (>>=) in Haskell and my question
| was "ok, but what does that have to do with IO?!?"
| grumpyprole wrote:
| The creator of LINQ, Erik Meijer, wrote a fun article "The
| curse of the excluded middle: Mostly functional programming
| does not work". Yes it's tongue-in-cheek and highly
| provocative, but many of his points are true. There is a lot
| more yet to be learned from functional programming than LINQ
| and switch expressions.
|
| https://queue.acm.org/detail.cfm?ref=rss&id=2611829
| aranchelk wrote:
| Is it meant to be tongue and cheek? I personally didn't get
| that impression. I assumed he was using the non-religious
| meaning of "fundamentalist": strict and literal adherence to
| a set of principles.
| grumpyprole wrote:
| I mean it has a deliberately highly-provocative style. But
| the points he raises are all completely valid.
| feoren wrote:
| This is _such_ a weird article. All of his examples are
| insane strawman non-idomatic C# code, and then he complains
| when they don 't do whatever he decides "an average
| programmer" would expect them to do. Huh? They were all
| either doing exactly what I expected them to do (silly
| things), or were so strange and alien that even Visual Studio
| has no idea what to do with them! I've never seen anything
| like that Cell<T> example and it doesn't come close to
| compiling. What a weird, weird thing to do: write code that
| literally _does not compile_ and then complain about it!?
| codingclaws wrote:
| This is off topic. I can't resist - that's the thickest sticky
| header I've seen from a developer.
| gorgoiler wrote:
| Yes, hah, I too was impressed with the chutzpah of having...
|
| "DANIEL"
|
| ...on a substantial amount of my screen throughout the whole
| read.
| JayGuerette wrote:
| His claimed inspiration, Hillel Wayne's post "Why Python is my
| Favorite Language", is a piece of fluff that basically says "I
| only like the things I already know". I was so _uninspired_ , I
| couldn't read further.
| loic-sharma wrote:
| You fault an article for being superficial while yourself only
| giving a superficial read? I hope you see the irony and
| reconsider.
| ur-whale wrote:
| Is there a FOSS compiler for F#?
| gameswithgo wrote:
| the Microsoft .net core compiler is FOSS, but if that doesn't
| count there is also mono.
| ur-whale wrote:
| > the Microsoft .net core compiler is FOSS
|
| Oh, I didn't know that.
|
| Very cool.
|
| Can I apt-get the toolchain?
|
| [EDIT]: and for those interested, here's the github repo:
|
| https://github.com/dotnet/fsharp/
| DeathArrow wrote:
| Yes, you can.
| ur-whale wrote:
| > Yes, you can.
|
| I can indeed. apt-get install fsharp
|
| (although it pulls in 300MB of dependencies :( )
|
| This is great.
|
| How times have changed!
| chusk3 wrote:
| I wouldn't do this, as this is the mono bundle of fsharp.
| The blessed/supported way to go now is to install the
| dotnet-sdk packages[1] and then use `dotnet fsi` for
| interactive work, and `dotnet build/run/etc` for project-
| based work in F#.
|
| 1: https://docs.microsoft.com/en-
| us/dotnet/core/install/linux-d...
| ur-whale wrote:
| I'll give it a shot, but TBH, I like the no-brainer apt-
| get way.
|
| Goal is not to spend a couple of hours fighting to
| install the stack, but to use the time learning about the
| language.
|
| apt-get gives me that.
|
| MSFT-specific stack install tool don't really sound like
| a no-brainer, but I'll look anyways.
| aloisdg wrote:
| As a fellow linux user, my package manager does the job
| for both the runtime and the sdk. It should work for
| yours too.
| enricosada wrote:
| See https://dotnet.microsoft.com/download
|
| Download the Sdk, who bundle both the runtime and the C#/F#
| compilers (everything you need to build a program) and the
| `dotnet fsi` REPL
|
| All of that is open source, developed in different repos
| and bundled there in a nice installer.
|
| Support all platform and can cross compile for other OS
|
| Please do not use Mono, because contains an old version of
| F# and lots of quirks to use.
|
| The current way is .NET (was called .NET Core, renamed
| recently) because is cross platform by design, and
| eventually Mono will be merged 100% there.
|
| Plus is tons more performant and better tooling
| ddek wrote:
| You can, but I wouldn't. The dotnet CLI contains its own
| version manager, so you need to have more precise control
| over the versions of the runtime & sdk you have installed.
| You can have multiple versions installed simultaneously,
| dotnet then chooses the runtime based on the project. IME
| linux package managers mess this up bad.
|
| Fortunately MS provides a better alternative: the dotnet
| install scripts. [0] Make sure you add the install
| directory to $PATH.
|
| [0] - https://docs.microsoft.com/en-
| us/dotnet/core/tools/dotnet-in...
| ur-whale wrote:
| > so you need to have more precise control over the
| versions of the runtime & sdk you have installed
|
| Oh, this doesn't sound good at all.
|
| One thing I positively _hate_ about Java is always having
| to worry about which version of this and that (sdk, vm,
| headless, etc...) you run on top of. The claim of write
| once run anywhere has not really happened in my book.
|
| Even C++ is better in that regard these days.
|
| I am certainly hoping the .NET / F# environment didn't
| inherit that attribute from the Java ecosystem, that'd be
| a major downer.
|
| My goal is only to learn F# / experiment with it, and I'm
| certainly hoping _never_ to have to spend a second
| thinking about "versions of the runtime & sdk".
| piaste wrote:
| If you just want to learn, install the latest version of
| the SDK (.NET 6, currently in RC) and it will be able to
| build code or reference libraries from every older
| framework version.
|
| Runtime versions are something you worry about when you
| are actually deploying / distributing applications.
| orra wrote:
| > Oh, I didn't know that.
|
| In fact, F# has been open source longer than Roslyn (the
| C#/VB.NET compilers) and .NET Core!
|
| There used to be a funny split in the repos: Microsoft had
| their own visualfsharp repo, and there was a blessed fork
| which was more community and Linux friendly.
| BBC-vs-neolibs wrote:
| ... to be clear, Mono does not provide F#. Microsoft releases
| F# for Mono.
| UK-Al05 wrote:
| F# and .net core are completely open source. You don't need
| mono.
| Smaug123 wrote:
| You can simply contribute to https://github.com/dotnet/fsharp/,
| the maintainers are very friendly to new contributors in my
| experience (though the codebase is _old_ and often quite hard
| to understand).
| phillipcarter wrote:
| > though the codebase is old and often quite hard to
| understand
|
| Even some new stuff is like that - and partially my fault,
| depending on the area :)
|
| That said, some stuff that was REALLY tough to understand was
| ripped out recently, the "reactor queue" and incremental
| build system. They were central to how editor tooling works
| and utterly incomprehensible since they were working around
| the lack of a free-threaded compiler service. Now the entire
| compiler is free-threaded, so all the complex machinery to
| coordinate work is mostly deleted and/or reduced to like 50
| lines of straightforward code.
| enricosada wrote:
| As a note, the codebase is also huge because contains lot
| of code:
|
| - FSharp.Core library, who contains most of the types and
| functions you want to use
|
| - the fsc F# compiler
|
| - the FSharp.Compiler.Service, who is the compiler as a
| library used by all editors/ide, written to be performant
| and support the logic of IDE functionalities (find
| references, etc)
|
| - The Microsoft Visual F# code, who is the F# extension for
| Visual Studio
|
| So is complicated repo, but for a reason. But nice to work
| with given the features there
| steve76 wrote:
| > Scott Wlaschin's fsharp for fun and profit is one of the best
| functional programming resources I know across all functional
| programming languages.
|
| Hey! Someone else saw this. Very underrated resource. Also
| Professor Frisby's Mostly Adequate Guide to Functional
| Programming needs more attention too.
|
| Things I would add:
|
| 1. Start off with what types you need, not functions. Creating
| your types like the tools you need to do the job. Then build
| combinators. Convert one complex type to a primitive. Then a
| primitive to your type.
|
| 2. Once you have your types, it's not that difficult to make them
| functional. You just make methods for "of", or "chain", or "map",
| or "ap". Now you have monadic and applicative interface.
|
| 3. The functional part is just like when a shell drops to a
| program's prompt, like >ftp and >mysql. You setup a series of
| commands like that, with Either or Task or Fold. Provide input,
| prepare a list of commands, and then run them when everything is
| valid and ready.
|
| 4. Bundle size is a problem for web. Until tech improves and
| bandwidth prices lower, 100 KB on a high volume website is a
| problem. Nothing wrong with taking a proven solution, like
| wordpress, and caching it.
|
| 5. Property based testing is for under the hood, your types and
| combinators. It's not something you do with Cypress or units. All
| that input is type unknown, and needs validation before going to
| what's coverage under property based testing.
|
| 6. One fault that always occurs is trying to use Runtime encoding
| to build some extensible modular program. Don't do that. Types
| are for build. Validation is for runtime. If it doesn't validate,
| show a user a message. Don't try to build some hot swappable
| modular program, where types are read from input. If they want to
| program the computer, they can install the IDE.
| rcarmo wrote:
| Pretty much on point. I've been building a .NET, bootstrapped
| webapp (i.e., no Razor, no "cargo culting" so I can actually
| understand things from the ground up) piecemeal, every other
| weekend, in both C# and F#, and, like Java before it,
| _understanding the ecosystem and libraries_ is critical.
|
| I can read OCaml and dabbled in it, but that doesn't help me
| write substantially better .NET because I will be iterating over
| lists or graphs in a different way, handling IO (and sockets)
| differently, etc.
|
| But I can see how someone conversant with C# and the .NET
| ecosystem would really like F# since the barrier to entry is
| substantially lowered, and the code is just so much nicer and
| tidier.
|
| Shame there isn't a proper AOT-compiled LISP for .NET (no,
| Clojure doesn't count, I never managed to get the .NET version to
| work for me).
| mickjagger wrote:
| What does F# do that other languages don't? What it's unique
| benefit?
| brightball wrote:
| I believe it's the functional language option on top of .NET.
| From what I understand, it's a pretty well designed one too.
|
| I don't work in the .NET ecosystem, but I know if came up a lot
| when I was getting into Erlang/Elixir.
| mjul wrote:
| Type providers are novel.
|
| It is a mechanism to provide type safe access to structured
| data and data services with almost no code. It feels like
| magic.
|
| Like other ML-derived languages (F# is an OCaml dialect) it has
| algebraic data types and pattern matching to make code simple
| and complete without missing edge cases.
|
| Also, it is arguably the best functional language on .NET, so
| it has a great platform with a large ecosystem to build on. And
| the tooling is great (Jetbrains, Microsoft IDEs).
| aloisdg wrote:
| > it is arguably the best functional language on .NET,
|
| it is also the only real one. On .NET we have C#, C++ and
| vb.net then there are some other fringe langs like IronPython
| or IronRuby and I think there is a PHP one too.
| aloisdg wrote:
| I forgot Boo and Nemerle. They are quite niche languages
| though.
| runevault wrote:
| I haven't done as much as I would like with them, but I feel
| like until someone tries type providers they don't get just
| how powerful they are. Being able to point to an example .csv
| file and have it generate the classes for you, and update
| them if you change said format, in a way that it ensures the
| types still work, is amazing. And you can do it for ANYTHING
| as long as you have a way to extract the data to feed it to
| the compiler.
|
| I still need to learn how to write a type provider just so I
| can.
| DeathArrow wrote:
| Functional, readable, easy to learn, as performant as C#, has
| the benefit of huge .NET ecosystem of libraries.
| enricosada wrote:
| For me is that pratically every time, if compile, it works.
|
| It's really easy to express a domain (with discriminated union
| and type) and the defaults (immutability, option, removal of
| boilerplate, high order function to manipulate data, structural
| comparison not reference) allow me to write correct code, who
| is readable without too much friction.
|
| Support a repl as first class, so that works too if you like
| repl driven development
|
| Community is also nice
| de_keyboard wrote:
| It's the _combination_ of features which is killer. I don 't
| know of another language that offers all of these:
|
| - Expression orientated
|
| - Lightweight syntax
|
| - Emphasis on immutable data and pure functions
|
| - do-notation (in F# these are called Computation Expressions)
|
| - Type-safety without _too_ many annotations (global type-
| inference)
|
| - Mainstream ecosystem of libraries (in this case .NET)
|
| - Compile to JavaScript
| KurtMueller wrote:
| Units of measure is also very cool!
| Smaug123 wrote:
| It's just really pragmatic about the upsides of functional
| programming. It describes itself as "functional-first", but
| isn't afraid to fall back on OOP in situations where OOP really
| does model the situation better.
|
| In my mind, it's taken the easiest 80% of the features of a
| true functional language, but then picked a pragmatic point at
| which to stop; the result is a language which is easy to learn
| and also makes it easy to use "most" of the good things you
| want from a functional language.
| barrenko wrote:
| When I learn Haskell, I'll be lot closer to God.
| StreamBright wrote:
| F# has become my default goto language. It is absolutely amazing
| to create cloud services in it an I have a small ETL tool as
| well. I would not trade it for anything else.
| jgwil2 wrote:
| Link to _What I wish I knew when learning Haskell_ is broken
| because it has https. The correct link is
| http://dev.stephendiehl.com/hask/ in case anyone was looking for
| it.
| AlbertCory wrote:
| That it's the same as Gb (on a piano or fretted instrument)?
|
| (Sorry. Couldn't resist.)
| AtNightWeCode wrote:
| In my area there was a huge push for functional programming and
| F# some years ago. A long time ago since I heard anybody working
| with F#. Clojure is somewhat popular though in fintech.
|
| Functional programming is something I think one should learn
| cause the concepts are useful in other programming languages too.
| Over time what is useful in functional programming languages will
| be available in other languages. In fact, a lot already is.
| Functional programming is not an USP in my world.
|
| When I started with C#, code bases were full of GoF patterns, if
| and switch statements were banned, there were hierarchies of
| inheritance, there were states spread out and encapsulated
| everywhere, static functions were banned. Today, code bases are
| mostly stateless except for things that needs to be reused, there
| are pure functions everywhere, inheritance is mostly used in
| libraries and where interfaces can't be used (yet), switch is ok
| and pattern matching is around the corner in several languages.
|
| More unpopular opinions. Immutability is overrated. In some
| programming styles, in some old languages there was a high risk
| of changing something by accident. Typical cause people did not
| know if they were working on a reference or a copy. Also, it was
| common to change fields on purpose. This problem does not really
| exist in a lot of programming languages today. But I do wonder if
| Go coders code benefit from some more immutability.
|
| I think the future of F# looks very dark but the functional style
| of programming will for sure have its place. What could change
| this is if F# really excels in some area like Go have done.
| vasergen wrote:
| I wish I have Elixir with types like in F#
| Rapzid wrote:
| I wish F# had a project comparable to Phoenix to boost its
| visibility.
| 7thaccount wrote:
| The biggest for me is needing to understand the .NET ecosystem
| without knowing C#. Then there's the lack of beginner
| information. I own several F# books and none of them assume
| you're coming from a scripting language background. I eventually
| gave up for good. OCaml doesn't have the .NET problem, but I
| found it to be unergonomic in a lot of ways.
|
| Make no mistake, it's a cool language that I'd love to be good
| at. The code always looks elegant, I'm just terrible at writing
| it.
| devmunchies wrote:
| I had the exact same problem. Even all the http servers had a
| lot of .net boilerplate to get started. A lot of that should be
| abstracted. I built an http server library that abstracts the
| .net parts. https://wiz.run/
|
| The hello world server: open Wiz.Server
| open Wiz.Context open Wiz.Route let myHandler
| ctx = ctx |> sendText "Abra Kadabra Kalamazoo!"
| let myRoutes = [ get "/" myHandler ]
| genServer() |> setRoutes myRoutes |> run
| devmunchies wrote:
| thinking more about it, F# needs to appeal to non-dotnet
| developers and other developers looking for a functional
| language for real workloads.
|
| F# currently seems easiest for c# dev to get started, but c#
| devs have almost no incentive to do so.
| SBArbeit wrote:
| I could say the same thing about any language. For
| instance:
|
| "Python needs to appeal to C# developers and other
| developers...
|
| Python seems easiest for PHP devs to get started, but C#
| devs..."
|
| And, the truth is, no, Python doesn't need to do that at
| all. It just has to be the best Python it can be.
| xhevahir wrote:
| Using Python doesn't require you to learn a (big) second
| language before you can do anything useful, though. F#
| arguably does. Maybe that is the best F# that F# can be.
| Which, for a lot of people, is not good enough.
| DeathArrow wrote:
| There are several good books like:
| https://www.amazon.com/Stylish-Crafting-Elegant-Functional-C...
| and https://www.amazon.com/Get-Programming-guide-NET-
| developers/... and also some courses on Udemy like:
| https://www.udemy.com/course/fsharp-from-the-ground-up/ and
| https://www.udemy.com/course/hands-on-f-application-developm...
|
| Also there are lots of learning resources here:
| https://fsharp.org/learn/ some for guys coming from scripting
| languages like Python. As a matter of fact, F# can be used for
| scripting, too.
| 7thaccount wrote:
| I'm not saying that you can't write an F# script, but that
| the path to getting one written is not obvious to those
| coming from scripting languages that are much simpler than
| the VAST .NET & JVM ecosystems. There is always some bizarre
| .NET arcana that gets in the way.
| orra wrote:
| Ah, that's interesting.
|
| I'm a huge fan of F#, but I had the advantage of knowing .NET
| first.
| barrenko wrote:
| Kinda agree, but F# works much better for me with my knowledge
| of .NET than e.g. Clojure with my understanding of Java.
|
| It's a cliche saying, but for me F# just works! (tm)
| Decabytes wrote:
| This was my issue when trying to learn clojure as well
| billfruit wrote:
| Yes, my experience as well. Clojure is more "lisp for java
| programmers" than "java for lisp programmers".
|
| Most of introductory material I found was good in explaining
| functional concepts, lisp approach to solving problems etc,
| but I thought assumed a working knowledge of the JVM
| ecosystem.
|
| For someone utterly unfamiliar to Java/JVM world would find
| clojure extremely baffling, cryptic error messages, needing
| to be familiar with the rather large java standard library,
| etc.
| 7thaccount wrote:
| Same. F#, Clojure, Scala, & Kotlin have all been the same for
| me. Python's VM is written in C, but I have no reason to know
| C. In Clojure they have you call out to Java libraries a ton.
| Someone always tells me that this isn't true on here, but it
| was my experience as well. Having to learn so many tools like
| emacs or CIDRE or Leinegen was also a turn off.
| gorjusborg wrote:
| I really love Clojure, but I have a lot of experience on
| the JVM so I didn't have to climb multiple learning curves
| simultaneously.
|
| While the clojure ecosystem has a lot of wonderful, bright
| and helpful people in it, and clojure itself is technically
| impressive (esp. its collections implementation), the new
| user experience isn't great.
|
| I'm not an experienced emacs user, so that makes it doubly
| difficult, as the ironed-out workflows seem to assume that
| you are (which is fair, as emacs and lisp are like peanut
| butter and jelly). However, these days it's fair to assume
| that a new clojure user is probably learning 'clojure',
| 'lispy ways', 'java/jvm', and 'emacs' simultaneously.
|
| I think that calva/vscode has a lot of potential to drop
| emacs off that list, which is welcome, as its learning
| curve alone is legendary. If you look at that list, it
| should not be surprising that the community is small.
| There's so much to learn that I it seems too much to even
| start.
| kaliszad wrote:
| There are multiple options to approach the Clojure*
| ecosystem. But yes, it is more focused towards dedicated
| and experienced developers overall. I use IntelliJ Idea +
| Cursive for development and that seems quite comfortable.
| I have a very rough sketch of the environment setup for a
| real app here: https://www.orgpad.com/s/hfxYQYkcLYV We
| use a similar setup to develop OrgPad itself.
|
| You can use Babashka https://github.com/babashka/babashka
| for a quick and dirty setup to get you up and running
| quickly. That is also useful for scripting some things.
| You might also try shadow-cljs + ClojureScript, if you
| are more at home in the Node.js/ Browser JavaScript
| ecosystem and want to do something with it. There is a
| new "(Not)Babashka" but built on ClojureScript:
| https://github.com/borkdude/nbb that might be interesting
| as well.
|
| I have found this video by James Trunk:
| https://youtu.be/C-kF25fWTO8?t=848 to have a very nice
| live coding example.
| barrenko wrote:
| Clojure is pretty cool, but I've come to understanding
| that as a beginner I would have been better off just
| learning good old Lisp.
| dboreham wrote:
| Haskell doesn't call out to anything.
| pjmlp wrote:
| That is the issue with any guest language, because it is
| impossible to hide the platform, unless the language is so
| constrainted that is practically useless.
|
| It is a hard to swallow truth, but guest languages really
| require understanding of the underlying platform.
|
| Another example, no matter one's opinion on C or JavaScript,
| mastering them is a much more confortable life on UNIX/POSIX
| platforms and browsers than trying to pretend they aren't
| there.
| 7thaccount wrote:
| Agreed. I think you say it more succinctly.
|
| It can also be frustrating if you know a little OO (but not
| how Java does everything) and then try to learn a
| functional language that sits on top of one of these OO tar
| pits of an ecosystem. I can write Python classes, but
| seeing the complicated mess of Java is frustrating as that
| has to be learned as well. Nothing against Java btw (it has
| its place), but it does seem to require a lot of
| boilerplate.
| mumblemumble wrote:
| First off -- I don't really want to get into bickering
| about Java is OO or not.
|
| That said:
|
| I think that Java is best understood as an enterprise
| programming language, not as an object-oriented one.
|
| There's a very peculiar class of programming languages
| that are a product of a specific period of history. At
| the time, companies were looking for ways to scale beyond
| the limits of the then-dominant procedural programming
| paradigm. But they had a lot of existing investment in
| it, and so teams were naturally hesitant to abandon it
| entirely.
|
| This situation created an ecological niche that allowed a
| very peculiar class of programming language to take root.
| Java and C++ are the best-known examples, but there were
| others such as Objective-C. C# and Visual Basic.NET are
| probably the last notable examples. These were multi-
| paradigm languages that layered object-oriented features
| on top of procedural bones. Earlier examples such as C++
| and Objective-C made this quite explicit, and were likely
| to even have their atomic types not be objects. Later
| examples eliminate some features such as non-object types
| and global functions and variables, but still retain much
| of their procedural heritage if you know what you're
| looking for. Probably the most notable one here is a
| tendency to favor explicitly state-oriented idioms over
| properly encapsulating state.
|
| Java falls somewhere in the middle. It has later features
| like full-fledged garbage collection, but lacks others
| such as a consistently object-oriented type system.
|
| I think that its tendency toward boilerplate directly
| reflects its stage in this evolution. Basically, what we
| perceive as boilerplate is really a hold-over from how
| procedural languages tended to be generally less
| declarative - it was up to the programmer to handle a lot
| more stuff for themselves.
| rixkys wrote:
| I'm surprised, I found clojure even while I was a pretty much
| total beginner programmer fairly easy to get into, via
| clojure for the brave and true at least was very good for
| getting the basics.
| WillPostForFood wrote:
| Clojure for the brave and true shows the exact problem.
|
| Chapter 1: install and learn the JVM
|
| Chapter 2: Emacs
|
| Chapter 3, finally start learning Clojure if you made
| through the first two chapters. Those first two chapters
| are going to filter out quite a few potential Clojure
| learners.
| 7thaccount wrote:
| Even that involves downloading and installing a fair amount
| of build tool stuff which may be necessary, but just drove
| me away.
| phillipcarter wrote:
| There's definitely room for a book or blog series along the
| lines of "F# for python programmers" or something.
|
| Unfortunately there's some level of .NET tooling you need to
| understand before you can do much today, and several .NET
| concepts creep in with that.
|
| The good news is that .NET Interactive is shaping up to be a
| great way to avoid most of that. At least so far all you need
| to do is install the .NET SDK, then install a VSCode plugin and
| you're good to go - just write code like you would in a python
| notebook, and acquiring packages is even easier than in Python:
| https://github.com/dotnet/interactive#notebooks-with-net
| dharmaturtle wrote:
| Linking your demo of VS Code Notebooks cause it was great:
| https://youtu.be/_QnbV6CAWXc?t=1298
___________________________________________________________________
(page generated 2021-10-14 23:01 UTC)