[HN Gopher] Verified Programming in F*: A Tutorial
___________________________________________________________________
 
Verified Programming in F*: A Tutorial
 
Author : jstrieb
Score  : 144 points
Date   : 2021-01-04 09:04 UTC (13 hours ago)
 
web link (fstar-lang.org)
w3m dump (fstar-lang.org)
 
| tartrate wrote:
| How's the interop with .NET and C#?
 
  | wisam wrote:
  | Are you thinking F#?
  | 
  | I believe that other than being ML-like language and being
  | developed jointly by Microsoft Research and Inria, F* has
  | nothing to do with F# and .NET.
 
    | tartrate wrote:
    | No I was just hoping it was connected somehow. I only found a
    | single mention of .NET:
    | 
    | > F* provides a facility to specify interfaces to external
    | modules that are implemented elsewhere. For example,
    | operations that perform file input/output are implemented by
    | the operating system and made available to F* programs via
    | the underlying framework, e.g., .NET or OCaml.
 
    | studius wrote:
    | "Programs written in F* can be translated to OCaml, F#, and C
    | for execution. ... The latest version of F* is written
    | entirely in a common subset of F* and F#, and bootstraps in
    | both OCaml and F#."[1]
    | 
    | [1]- https://en.wikipedia.org/wiki/F*_(programming_language)
 
      | wisam wrote:
      | Thanks, I stand corrected.
 
| bibelo wrote:
| Who reads f * * * instead of f*?
 
| sdfjkl wrote:
| I find the syntax both terrible to read and terrible to write.
| 
| Syntax is what I look at first with any unfamiliar programming
| language. The syntax is the UI of a language and if that's
| terrible, I won't enjoy using it.
 
  | dragonwriter wrote:
  | > I find the syntax both terrible to read and terrible to
  | write.
  | 
  | I don't, but then I've spent time with a variety of languages
  | that, like F*, are from the ML syntax family, and find that
  | syntax quite comfortable.
  | 
  | I can see why it would seem that way at first impression to
  | someone who, for instance, has almost exclusively used
  | languages with Algol-derived syntax (which is pretty common
  | these days, since outside of Haskell from the ML family and
  | Clojure from the Lisp family, most currently popular languages
  | have Algol-derived syntax, or at least superficially Algol-like
  | syntax.)
  | 
  | > Syntax is what I look at first with any unfamiliar
  | programming language.
  | 
  | It's one of the things I look at early on, too, but it's also
  | something I try to not to judge to firmly early on, because
  | subjective view of syntax, like other UI impressions, is highly
  | dependent on familiarity, and it takes a while to get past
  | superficial similarity and dissimilarity to what one is used to
  | and into any deeper strengths and weaknesses of the syntax (or
  | other UI).
 
  | gameswithgo wrote:
  | people get used to syntaxes, by avoiding languages that don't
  | immediately appeal to your current syntactic preferences you
  | are missing out on actual important and interesting ideas over
  | triviality that would go away with familiarity
 
  | amw-zero wrote:
  | What's an example of a language with a good syntax?
 
    | mhh__ wrote:
    | I think Python (if nothing else) has good syntax. Forcing
    | students not to write spaghetti is probably the only thing I
    | actually like about python.
    | 
    | I really like the philosophy behind Haskell, for example, but
    | I really think it's syntax let's it down - it encourages very
    | snippet-y programming which in turn means structure can be
    | require parsing rather than glancing at and also variables
    | name that are very short.
 
  | sanxiyn wrote:
  | Since syntax of F* looks okay to me, I am curious what
  | particular points of syntax of F* you find terrible to read and
  | write.
 
    | idnefju wrote:
    | In general I like ML based syntax, but Haskell using type
    | signatures really helps read code easier. Wish other
    | languages would adopt them
 
      | paavohtl wrote:
      | I don't understand this critique with regards to F*. As far
      | as I can tell it has a type signature syntax that is very
      | similar to Haskell, and is used extensively in the linked
      | tutorial.
 
  | haskellandchill wrote:
  | It's the ML family of languages syntax, very familiar if you've
  | studied programming languages. Not sure what you can find
  | terrible about it, it's a clean and minimal syntax.
 
| dang wrote:
| If curious see also-- related from 2016:
| https://news.ycombinator.com/item?id=10949288
 
| co_dh wrote:
| Just joking: will the version 3 called f***?         I like the
| language btw.
 
| the_only_law wrote:
| I've recently had a interest in formal verification in regards to
| programming, but my background is so god awful I'm afraid to
| approach it. How does F* fair for beginners with little prior
| exposure?
 
  | ernst_klim wrote:
  | > but my background is so god awful
  | 
  | I suggest you to read (or rather solve) this masterpiece
  | 
  | https://softwarefoundations.cis.upenn.edu/
 
  | haskellandchill wrote:
  | This tutorial aims to be beginner friendly, assuming you have a
  | background in functional programming. However the pace is very
  | brisk and would serve better for an intermediate learner
  | familiar with the concepts. As a practical tool it would not
  | provide much unless you really know what you are doing and plan
  | to leverage the use of SMT Solvers and code generation. You'd
  | be better off with simpler and more focused learning materials.
  | The Little Prover or Software Abstractions for example.
 
| yetkin wrote:
| "It will help if you are already familiar with functional
| programming languages in the ML family (e.g., OCaml, F#, Standard
| ML), or with Haskell--we provide a quick review of some basic
| concepts if you're a little rusty, but if you feel you need more
| background, there are many useful resources freely available on
| the web, e.g., Learn F#, F# for fun and profit, Introduction to
| Caml, the Real World OCaml book, or the OCaml MOOC."
| 
| Isn't it yet another copy of OCAML? I think it shouldn't say
| familiar but something different. I really don't underestimate
| any effort to make OCAML available on dot-net, but referring to
| excellent OCAML books can't be explained by simple
| 'familiarity'...
 
  | vmchale wrote:
  | > Isn't it yet another copy of OCAML
  | 
  | No, closer to ATS maybe?
 
  | scscsc wrote:
  | You are probably thinking of F#, not F*. Very different
  | languages.
 
    | studius wrote:
    | "Programs written in F* can be translated to OCaml, F#, and C
    | for execution. ... The latest version of F* is written
    | entirely in a common subset of F* and F#, and bootstraps in
    | both OCaml and F#."[1]
    | 
    | https://en.wikipedia.org/wiki/F*_(programming_language)
 
      | travv0 wrote:
      | I'm not sure what point you're trying to make with that
      | quote. The languages that F* can be compiled to and the
      | ones it's written in aren't relevant to what was being
      | discussed.
 
      | RobertKerans wrote:
      | Why is that relevant though? You could also write a version
      | of (for example) Prolog or Forth or Lisp using OCaml that
      | would compile to OCaml for execution. Doesn't mean any of
      | those are OCaml. Coq isn't OCaml. Haxe isn't OCaml. The
      | fact that F* is written in, uses a subset of the syntax of
      | and can be compiled to F# (or OCaml) is an implementation
      | detail, the language and the purpose of the language aren't
      | to be OCaml/F#.
 
| estebarb wrote:
| F* is a great idea for writing libraries that cannot fail. But
| setting up the environment could be better documented.
 
| adsharma wrote:
| Also see: https://rise4fun.com/fstar/tutorial
| 
| Even though this sounds like formal verification gobbledygook,
| there is some information of practical value there.
| 
| How many JSON validators have you seen in python and javascript?
| Why can't the static type checkers like mypy and pyright do this
| for us?
| 
| The answer is that the type systems of these languages are not
| sufficiently developed. They can tell you if you're assigning a
| string to an int, but not if you're assigning 200 to an int whose
| type allows only numbers in [10, 100].
| 
| So one creates a new class with a validate() method, which is
| completely unnecessary and doesn't protect you against integer
| overflows elsewhere in the code.
| 
| F* and OCaml derivatives are our best hope in developing a type
| system which perform these types of common checks in one
| integrated framework via refinement types and dependent types.
| 
| Hopefully, one day that work can hit mainstream languages like
| python, javascript and whatever ends up being the system
| programming language of choice replacing C in the coming years.
 
  | dragonwriter wrote:
  | > How many JSON validators have you seen in python and
  | javascript? Why can't the static type checkers like mypy and
  | pyright do this for us?
  | 
  | Because JSON is external data, mypy and pyright operate on
  | Python code.
  | 
  | > They can tell you if you're assigning a string to an int, but
  | not if you're assigning 200 to an int whose type allows only
  | numbers in [10, 100].
  | 
  | Mypy can, in fact, do that (via a union of literal types),
  | though the UX is horrible for that specific case and it only
  | handles simple literals, but that's actually enough for JSON
  | semantics. Of course, to validate JSON with it, you'd have to
  | turn the JSON into Python code with type annotations and
  | validate that.
 
  | com2kid wrote:
  | > The answer is that the type systems of these languages are
  | not sufficiently developed. They can tell you if you're
  | assigning a string to an int, but not if you're assigning 200
  | to an int whose type allows only numbers in [10, 100].
  | 
  | I am pretty sure Ada did that in the 80s. :)
  | 
  | I get what you are saying, but the example you gave is a pretty
  | trivial one that has been solved (although not implemented very
  | often...) for awhile in more "regular" languages!
 
    | adsharma wrote:
    | I picked the trivial example on purpose to make the point
    | that none of the top 5 programming languages do it, even if
    | it was solved in the 80s.
    | 
    | Recent languages like swift/kotlin (which I expect will see
    | increased usage in coming years) seem to have ignored this
    | area.
    | 
    | https://github.com/peter-tomaselli/swift-
    | refined/blob/master...
    | https://discuss.kotlinlang.org/t/refinement-types/9753/19
 
      | ampdepolymerase wrote:
      | Because it requires a non-trivial amount of static analysis
      | work on the compiler side to make the UX comfortable.
      | Rust's borrow checker mechanism took years to become
      | pleasant for the end user to use. There is still next to no
      | adoption of Ada outside of aerospace, defence, and certain
      | embedded programming sectors.
 
      | com2kid wrote:
      | It is super annoying that it isn't done more.
      | 
      | I'd love to be able to opt in to bounds checking when I
      | feel it is needed.
      | 
      | I have no bloody idea why language designers seem so intent
      | on not letting me choose what perf/safety trade-off is
      | worthwhile for me. :/
 
        | pjmlp wrote:
        | Easy, use C++.
        | 
        | While not perfect, given its copy-paste compatibility
        | with C, you can opt-in into bounds checking by using the
        | STL data types, or similar.
        | 
        | Then you can also make use of compiler switches, to opt-
        | in in changing the behaviour of operator[]() to do bounds
        | checking.
        | 
        | With templates, you can opt-in into checked numerics.
        | 
        | While not perfect, and maybe it will be replaced by Rust
        | or other candidate someday, it already offered plenty of
        | opt-in possiblities since early 90's, no need to keep
        | writing C.
 
  | z3t4 wrote:
  | Type systems do not thinking for you, you still have to make a
  | type with a range check. So you could just as well write
  | function foo(n) {         if(n < 10 || n > 100) throw new
  | Error("Expected n=" + n + " to be between 10 and 100");
  | return n*2;       }
  | 
  | And while you are at it you can write an unit test that is
  | tested at compile time or in the editor/IDE.                 //
  | assert(foo(10),20);
 
    | amw-zero wrote:
    | Try reading the tutorial. F* uses refinement types, which
    | means that logic is checked before the program is executed,
    | at compile time.
 
| keyle wrote:
| I'm confused. Is this either very new or very old? What's the
| context?
 
  | sradman wrote:
  | According to the F* landing page [1]:
  | 
  | > F* (pronounced F star) is a general-purpose functional
  | programming language with effects aimed at program
  | verification.
  | 
  | > The main ongoing use case of F* is building a verified, drop-
  | in replacement for the whole HTTPS stack in Project Everest
  | [2]. This includes verified implementations of TLS 1.2 and 1.3
  | and of the underlying cryptographic primitives.
  | 
  | [1] http://www.fstar-lang.org/
  | 
  | [2] https://project-everest.github.io/
 
  | mmoskal wrote:
  | F* primary aim is correctness - think something between
  | Coq/LEAN/Isabelle and OCaml/F#. It uses a dependent type system
  | to verify deep functional properties of programs (say that
  | qsort actually sorts, or that a tree is balanced and implements
  | a mathematical map).
  | 
  | Typically such languages are more academic than F*.
 
    | wolfspider wrote:
    | I would also say take a look at Bosque it is also from the
    | same camp as F* but much simpler to use Z3 with.
 
  | vmchale wrote:
  | Fairly new language.
 
  | ivarru wrote:
  | As pointed out by dang, the same (I think) tutorial was
  | discussed in 2016
  | (https://news.ycombinator.com/item?id=10949288). I went through
  | the first half of the tutorial in 2018, and I think some
  | aspects of F* were genuinely new, but the development seems to
  | have stopped. There is a need for a framework for program
  | verification of real-life software by non-experts, but F* might
  | not be it. In the latest article [1] of Project Everest one can
  | read: "[...], it required several person-months to implement
  | and verify a generic doubly-linked list library in F*, while it
  | required only three hours to do so in Dafny."
  | 
  | [1] A Security Model and Fully Verified Implementation for the
  | IETF QUIC Record Layer (Antoine Delignat-Lavaud, Cedric
  | Fournet, Bryan Parno, Jonathan Protzenko, Tahina Ramananandro,
  | Jay Bosamiya, Joseph Lallemand, Itsaka Rakotonirina, Yi Zhou)
  | To Appear In The Proceedings of the 42nd IEEE Symposium on
  | Security & Privacy 2021.
 
    | brundolf wrote:
    | it required several person-months to implement and verify a
    | generic doubly-linked list library in F*, while it required
    | only three hours to do so in Dafny
    | 
    | This could be deceptive. Structures like linked-lists are
    | fiendishly hard to implement in safe Rust too, but people are
    | able to stay productive by (mostly) not implementing things
    | like that themselves. In Rust's case the difficulty comes
    | from ownership: anything involving complex reference graphs
    | for the sake of traversal is going to be really gnarly to
    | establish a single-ownership story for. I don't know about
    | F*.
 
  | Multicomp wrote:
  | i am not familiar with fstar. But I will try to provide some
  | context badly so someone who does know it can correct me.
  | 
  | Javascript is dynamically typed, and so has no type checking
  | until runtime, you don't know whether a passed in parameter is
  | a string or not until you try to use it.
  | 
  | C# is statically typed, so the compiler knows whether something
  | is a string when passed in at compile time, not making you wait
  | until runtime.
  | 
  | Ocaml/F# have a stronger type system than c#, so you get the
  | compiler looking for you not only that something is a string,
  | but that it is a named type like fifteenString, which is a
  | string with a length of always 15 characters.
  | 
  | F* takes this even further, where the compiler checks for you
  | that you've passed in a fifteenString and that it matches
  | criteria in its value like "starts with hello" or "does not
  | contain bye".
  | 
  | C# saves you from needing to check if a param is even a astring
  | at runtime.
  | 
  | F# additionally saves you from needing to check if it is null
  | and 15 characters in length at runtime.
  | 
  | F* additionally saves you needing to check its value starts
  | with hello at runtime.
  | 
  | Again this is a single language feature probably poorly
  | explained!
 
    | globuous wrote:
    | Ocaml beginner here, didn't know you could restrict an Ocaml
    | type to a string of a given length !! How would you go about
    | that ?? Cheers :)
 
    | jen20 wrote:
    | The only difference between F# and C# with respect to the
    | notion of a "type which represents a string of length 15" is
    | the amount of code to do it - as described by Scott Wlaschin
    | [1]. You could do the equivalent in C# too. I don't know if
    | this is also the case in Ocaml, though.
    | 
    | [1]: https://fsharpforfunandprofit.com/posts/designing-with-
    | types...
 
| gautv wrote:
| How does the language compare to a language like Idris ?
 
___________________________________________________________________
(page generated 2021-01-04 23:01 UTC)