Live data from Hacker News

15-150: Principles of Functional Programming

brandonspark.github.io

121–130 of 146 posts

Re: 15-150: Principles of Functional Programming

#122
post #109

Earlier quoted context omitted.

Oh yeah, a pure function that accepts previous state, and returns the new state is the pattern I use a lot. The issue is that it is hard to do on complex graph structures in an algorithm where incremental changes happen to the graph O(n) times - it ends up creating complex code and complex execution that might be slow to pass the time limit on Codeforces, let's say. In the OCaml world maybe this is the place where yo…

Oh definitely go deep into monads. If you use the ST monad to do mutations, some people think Haskell provides nicer syntax to do imperative programming than traditional imperative languages like C. But of course such nicer syntax only comes from understanding and using important abstractions like monads, foldable, or traversable. Then there are niceties like automatic SoA/AoS transformation using type families.

I don't think I have heard of the automatic AoS/AoS before, do you have good links to study more?

Re: 15-150: Principles of Functional Programming

#123
post #118

Earlier quoted context omitted.

let* permits expressions on the right refer to arbitrary other symbols bound by the let*. in particular it allows for construction of recursive lambdas that may not be linearlizable.

> let* permits expressions on the right refer to arbitrary other symbols bound by the let* In what language? I just checked Elisp, SBCL, and Guile, and they all error out if you refer to a variable not previously defined by a left-to-right traversal of the varlist: (let* ((a (+ b 1)) (b 1)) a) Edit: This doesn't work either: (let* ((a (lambda () (+ b 1))) (b 1)) (funcall a)) ; (funcall a) -> (a) for Schemes

Anyway, as far as I'm seeing it's perfectly possible to implement let* consistent with the above behavior as a macro without mutation as such:

    (define-macro (let* bindings &rest body)
      (if (null? bindings)
        `(progn ,@body)
        `(let (,(car bindings))
           (let* ,(cdr bindings)
             ,@body))))

Re: 15-150: Principles of Functional Programming

#124

My complaint with FP: Sometimes I just want to do something silly, like adding a log somewhere. If I choose to add said side effect, now all my functions are marked with an io signature (so there might be _other_, nastier side effects hiding there as well - mainly an issue if you have multiple people contributing to the same project). If I don't add the side effect, and choose to refactor multiple layers of code, I w…

> If I choose to add said side effect, now all my functions are marked with an io signature

You got the wrong idea. You're supposed to write FP in a way where the side effect is highly layered and segregated away from pure code. IO are singularities within your chains of pure function compositions. As soon as you hit a singularity you have to break out of it as soon as possible.

The main idea is the meat. Keep your bread tiny and keep it very very separate from the meat.

The pattern is called Imperative Shell, functional core. Think of your IO as two pieces of bread in a sandwich and your pure code is the meat that connects the read to the write.

The game you're playing with haskell is to avoid letting the IO monad pollute any of your logic as much as possible.

Anyway that being said in applications where IO is all over the place... this pattern becomes largely ineffective. You basically have more bread than meat.

Re: 15-150: Principles of Functional Programming

#125
post #15

on the choice of language to teach the course why sml i think there are a lot of nicer choice OCaml , its basically sml only more popular and used more in real life Haskell , again more popular , and used more in real life Idris , newer and said to be more progressive F# , a more practical choice and similar to sml a lisp , well if you want to focus on the functional part and less on the types part

because SML is awesome, isn't going to change and is simple. you can learn the syntax in an afternoon, and really focus on learning FP semantics.

Albeit little, installing SML still requires some anount of gymnastics, google searching, and copying stuff from SO, GH Gists, etc.

Yes, I agree broadly with the line of thinking that says- if you are learning FP, you must be willing to do these, but a beginner might be disheartened and turned away- especially as someone learning alone.

Re: 15-150: Principles of Functional Programming

#126

Earlier quoted context omitted.

He is probably talking about namespaces. In common lisp, for example, (a a) calls a function 'a' on a variable 'a'. Lisp knows this because the first thing that comes after the left paren is a function

more importantly there are functions (using scheme as an example) like set! and set-cdr! that mutate existing values and totally break referential transparency. this isn't just user facing - for example let* kind of depends on creating bindings up front so they work across clauses, and then mutating them afterwards

Lisp allows you to mutate, you can certainly write non-mutating code in lisp. Why do you think you need to use mutation with let*? let* is just a sequential let

https://www.lispworks.com/documentation/lw70/CLHS/Body/s_let...

Re: 15-150: Principles of Functional Programming

#128

My complaint with FP: Sometimes I just want to do something silly, like adding a log somewhere. If I choose to add said side effect, now all my functions are marked with an io signature (so there might be _other_, nastier side effects hiding there as well - mainly an issue if you have multiple people contributing to the same project). If I don't add the side effect, and choose to refactor multiple layers of code, I w…

Others have mentioned having the same problem with this issue. One post I particularly like about the subject is this one on function colouring (how lagnuages with async/await syntax have a similar "infection"; this is a response to the original post on function colouring and not the original post). https://www.tedinski.com/2018/11/13/function-coloring.html

Re: 15-150: Principles of Functional Programming

#129
post #28

Great resource! Forgive my ignorance but why do so many modern functional programming courses use Standard ML instead of a Lisp dialect? Is it because of its built-in type-checking, or is it just how it's always been taught?

The value of purely functional programming languages, as opposed to functional programming languages like lisps, is that you get referential transparency, which means that when you define `a = b`, you know that you can always replace any instance of `a` with `b` and get the same answer. This is a very natural property in mathematics (algebraic rewritings are basically just this property writ large) and so it helps to…

The first problem with this argument is that referential transparency is a property of syntactic positions, not of languages.

The second is that languages like Lisp, SML, C, Pascal and BASIC all have referentially transparent and referentially opaque positions in exactly the same way that languages like Haskell do.

This means that all these languages enjoy referential transparency in the same way, because when you unpack the notion of equivalence, referential transparency itself is within a whisker of being a tautology: if a is equivalent to b, then you can substitute a for b or b for a. The relevant sense for "is equivalent to" can really only be contextual equivalence, which is all about meaning-preserving substitutability.

That said, not having to reason about effects within one's program equivalence sure makes things simpler in a pedagogical setting. But that's not to do with referential transparency per se.

Re: 15-150: Principles of Functional Programming

#130
post #113

Earlier quoted context omitted.

Why does `let*` need to have mutation? It can be nested `let`s.

let* permits expressions on the right refer to arbitrary other symbols bound by the let*. in particular it allows for construction of recursive lambdas that may not be linearlizable.

You're thinking of letrec.
Post reply on HN