Top products from r/fsharp
We found 11 product mentions on r/fsharp. We ranked the 9 resulting products by number of redditors who mentioned them. Here are the top 20.
4. CLR via C# (4th Edition) (Developer Reference)
Sentiment score: 0
Number of reviews: 1
Microsoft Press
5. Programming Language Concepts (Undergraduate Topics in Computer Science)
Sentiment score: 1
Number of reviews: 1
Used Book in Good Condition
> My other question is if F# good for some scientific applications?
Yes. I started out using F# for such things. I ended up writing the book on it.
F#'s ML core is extremely simple. I think you would find it very easy to learn. Let me get you started:
There is a type called
unit
that has a single value in it called()
that can be used to convey no information, a bit likevoid
in other languages but you can use the value()
of the typeunit
anywhere.The
bool
type has valuestrue
andfalse
.Integers are written
1
,2
,3
and so on. Integer arithmetic is1+2*3
. Theint
function converts a value (e.g.float
orstring
) into anint
.Floating point numbers are written
1.2
,2.3
,3.4
and so on. Floating point arithmetic is written1.2+2.3*3.4
. Thefloat
function converts a value (e.g.int
orstring
) to afloat
.Characters are of the type
char
and are written'a'
. Strings are of the typestring
and are written"foo"
. You can append strings with"foo"+"bar"
. Thestring
function tries to convert a value of another type (e.g.int
orfloat
) into a string.Lists are written
[1;2;3]
. You can prepend onto the front in constant time with1::[2;3]
.Arrays are written
[|1;2;3|]
. You can read and write elements with random access in constant time witharr.[i]
andarr.[i] <- 3
.ML has sum types and product types. The simplest product type is the tuple. Tuples are written
(2, 3)
and(2, 3, 4)
. The types of those tuples are writtenint * int
andint * int * int
. Tuples can have as many elements as you like (greater than one, of course). Note F# uses OCaml-style syntax which lets you drop many brackets when dealing with tuples, so you can often just write1, 2
.F# also has record types which are product types where the fields have names. Record types are defined as
type MyRecord = {FirstName: string; LastName: string}
. Values of record types are written{FirstName="Jon"; LastName="Harrop"}
. Given a valuer
you can get a field with the syntaxr.FirstName
. As a product type, a value of typeMyRecord
must have aFirstName
and aLastName
.Algebraic datatypes (ADTs) are a combination of sum types and product types. A sum type allows a value to be one of several different options. The simplest example is to define your own boolean:
type MyBoolean = True | False
The values
True
andFalse
are then values of the typeMyBoolean
. Like an enum in other languages. But the really cool thing about ADTs in MLs is that those union cases can have an argument of any type you want. For example, we can define an ADT:type Glyph =
| Digit of int
| Letter of char
The values
Digit 3
andLetter 'x'
are values of this typeGlyph
.The value
()
of typeunit
was a minor diversion from other programming languages. Now comes the first major diversion: pattern matching is the only way to destructure ADTs. So the only way to extract those values3
and'x'
from the value of typeGlyph
is using pattern matching. In ML there are patterns all over the place. The most obvious place you see patterns in on the left hand side of the->
in each match case of amatch
expression. Here is a pattern match that will keep digits the same but redact all letters to'x'
:match Digit 3 with
| Digit n -> Digit n
| Letter c -> Letter 'x'
In this case the
Digit n
andLetter c
are patterns. In particular, these have the effect of binding the variablen
to the value conveyed in theDigit
case (so it can be used on the right hand side of that match expression) orc
to the value conveyed in theLetter
case.You can match
int
,float
,char
,string
and other types such as tuples, records and ADTs using the same literal syntax that you do in expressions.When you need to match a value but you don't care about its value you can use
_
to match any value of any type and not bind it to any variable name.If you want your pattern to match either something or something else you can write an or-pattern:
patt1 | patt2
.If you want to name part of a value that you're matching you can use
patt as myVar
to call itmyVar
. For example, we could have written:match Digit 3 with
| Digit as glyph -> glyph
| Letter c -> Letter 'x'
You can define variables with
let
:let x = 3
This looks mundane but that
x
is actually a pattern so you can also do:let (x, (y, z)) = (1, (2, 3))
to destructure the
int * (int * int)
pair on the right and definex
,y
andz
.You can also define functions with
let
:let redact glyph =
match glyph with
| Digit -> glyph
| Letter c -> Letter 'x'
In ML, function application is written
f x
rather thanf(x)
, e.g.redact (Digit 3)
.Here we come to our second massive departure from conventional languages: when you have tuples you don't need multi-argument functions so every function in ML accepts one argument and returns one value! Furthermore, like OCaml, F# typically writes functions in Curried form. So a function to add two numbers is written
let add x y = x+y
which has the typeint -> int -> int
rather thanint * int -> int
so this is a function that takesx
and returns another function that takesy
and returnsx+y
.Oh look, you've learned enough F# to understand this computer algebra system that can differentiate any symbolic mathematical expression composed of integers, variables, addition, multiplication, power and logarithm:
type Expr =
| Int of int
| Var of string
| Add of Expr Expr
| Mul of Expr Expr
| Pow of Expr * Expr
| Ln of Expr
let rec d x e =
match e with
| Var y when x=y -> Int 1
| Int | Var -> Int 0
| Add(f, g) -> Add(d x f, d x g)
| Mul(f, g) -> Add(Mul(f, d x g), Mul(g, d x f))
| Pow(f, g) -> Mul(Pow(f, g), Add(Mul(Mul(g, d x f), Pow(f, Int -1)), Mul(Ln f, d x g)))
| Ln f -> Mul(d x f, Pow(f, Int -1))
For example, the symbolic derivative of
x^x
computed in F# Interactive (e.g. in Visual Studio) is given as:> d "x" (Pow(Var "x", Var "x"));;
val it : expr =
Mul
(Pow (Var "x",Var "x"),
Add
(Mul (Mul (Var "x",Int 1),Pow (Var "x",Int -1)),
Mul (Ln (Var "x"),Int 1)))
Probably the next thing to understand is that
map f [a;b;c;...] = [f a; f b; f c; ...]
andfold f a [b;c;d;...] = f (f (f a b) c) d) ...
. For example, if you represent 2D coordinates as a pair you can write:let translate (x0, y0) ps = Array.map (fun (x1, y1) -> x0+x1, y0+y1) ps
To sum a list of integers you can write:
let sum xs = Array.fold (fun x a -> x+a) 0 xs
So given a file containing a list of integers on separate lines you can add them all up with:
Seq.fold (fun total line -> int line + total) 0 (System.IO.File.ReadAllLines @"Data/Numbers.txt")
F# has a handy pipeline operator
|>
so you can writef x
asx |> f
instead. For example:System.IO.File.ReadAllLines @"Data/Numbers.txt"
|> Seq.fold (fun total line -> int line + total) 0
Another mind-blowing thing you'll come to love is purely functional data structures. When you add an element to a list, set or map (dictionary) in F# you get a new collection in O(log n) time but the old collection is still perfectly valid and can be reused.
\> Would it transpile ALL of my code into JS? Wouldn’t that degrade performance?
​
If you implemented your numerical computations in the Fable app, yes, most likely. Although JavaScript can be used to write performant desktop applications - for instance, Visual Studio Code - I don't think it would be a good fit for scientific computing. The use case for Fable is in having behaviorally-sophisticated UIs without having to run through the dynamically/weakly-typed mess that is JavaScript. That said, JavaScript is not a terribly slow language - the Node.js JavaScript runtime is typically faster than Python. And Fable has Electron bindings for creating desktop apps. It could be worth trying. But I imagine a transpiled F# program would be noticeably slower than having one run in the .NET Framework or .NET Core runtime.
​
You really want to think of this as a UI layer on top of a computation layer. For a web application, the UI is typically run client-side in JavaScript (the browser sends .JS code to its JavaScript runtime, or in the very simplest case is only an HTML renderer), while the server code is some other language (F#, C++, PHP, etc) that sends user-facing data to the JavaScript. For a .NET desktop application, it'll all be bundled and run in the same place, but typically with a separate frontend project and a backend project. Unfortunately, either way it'll be a bit of work. And I think we'd need a bit more information about your code to give a good answer - for starters, is this Windows, or Linux? .NET Framework or .NET Core?
> Delimited continuations are better than undelimeted (as I have read)
I wouldn't say they are better, but they are different in small ways. Delimited continuations are more complex, but with that complexity comes a notion of scope. Depending on what you're doing, that extra capability may or may not be better (okay, so usually it's better in real programs). So if you're designing a language or library that implements continuations you still have a trade-off between the added complexity of delimited continuations vs undelimited continuations.
Have you seen Andrew Appel's book "Compiling with Continuations"? I have not read it personally, but my understanding is that it is highly relevant to your question. Perhaps you can find an online preview to see if it would help you.
I think you would benefit a lot from "wrapping up" your continuations in a computation expression. In Haskell land, they have a continuation monad and it makes writing things in terms of continuations more convenient. For instance, here is an article meant to introduce beginning Haskell programmers to the Cont monad: https://wiki.haskell.org/All_About_Monads#The_Continuation_monad
The idea is that you create a continuation at each lexical point you may want (or need) to return to (say for instance, you want to return to the top level of the interpreter when you detect a division by zero). Creating the continuation gives you the 'escape hatch' that you may call later in the exceptional case. I think the haskell example makes this clear by calling the continuations "exit1" and "exit2".
I hope that helps.
i recommend functional programming using f#. i just picked it up myself and am enjoying it. the programming f# 3.0 book is also pretty good.
there's also programming language concepts. it's an introduction, although it doesn't play around, to exactly what it says, but it uses f# as a meta language to explore the concepts.
Programming F# is a very nice intro. That's the first book I read when I started to learn the language, and it served me well.
Functional Programming Using F#. The book focuses on functional programming, has a nice set of examples and nontrivial programming exercises. Also, if you're into MOOCs you could try this course that teaches ML. I struggled really hard with the course, but I learned a lot, and after ML it was really easy to start with F#.
it is common to not use oop patterns in game programming for performance reasons, even in c++ where you could oop if you wanted to. read up on entity component systems for one approach. totally compatible with monogame. you can do whatever you like inside its draw and update loops. you dont have to extend its gameobjects or anything.
DUs are often a fine alternative to OOP patterns. fill an array with entities, match to get which type, call a different function for each.
functions are a one liner interface
this book :
https://www.amazon.com/dp/1916478700/ref=cm_sw_r_cp_awdb_t1_tBiyCbZWNC42V
has really neat info on oop alternatives despite being geared toward c developers
you will usually want to mutate gamestate if performance is a concern but you may not have to. again monogame isn’t leading you one way or the other here.
I found this to be a good guide to .net: Pro C# 7: With .NET and .NET Core
I was reading CLR via C# the other day and something that struck me is how often the author talked about the advantages of being to use multiple languages that can talk with one another seamlessly due to them all running on the CLR. The author seemed disappointed that VB became C# with slightly different syntax while other languages on the platform weren't really getting much love.
With C# getting pattern matching in the next version, I do wonder how far and how large C# will become, ultimately, and if we'll see a more distinct push to have more varied usage of other CLR languages to solve particular problems.
Considering that Mark Seemann literally wrote the book on dependency injection in .Net, it's theoretically possible that he does understand all its nuanced complexities, and that dismissing this presentation (which is, naturally, simplified so it makes a good presentation) as "populist nonsense" is a mite hasty.