> It turns out that Haskell's non-strict semantics are a shockingly close match for the semantics of hardware
Doesn't Haskell need automatic memory management in order to implement higher-order functions, that being perhaps the most prominent difference in semantics between Haskell/Ocaml and Rust? Is Clash limited to first-class functions ala C?
No, clash supports higher-order functions just fine. The only thing it can’t really represent is general recursion. You need to use type-constrained recursion. Clash isn’t fully generalized yet so it provides some nice bounded recursion primitive.
Yes, but the Clash reference documentation states that it doesn't do behavioral synthesis. It structurally maps the representation of the supported subset of fully-applied Haskell functions to either combinational or sequential circuits, depending on whether the function takes a `Signal`-type argument. The fact that the representation is shared leads to many advantages compared to e.g. Chisel, but this is definitely a "shallow embedding" approach.
"Signal" is just [] without an empty constructor (i.e. a lazy corecursive stream). As far as your Haskell code is concerned, there is nothing special whatsoever about signals, and indeed it's just a normal data type until the Clash-specific Core layer kicks in.
I think I mixed up "shallow" and "deep" embedding - by "deep embedding", I meant to say that there is no secondary AST manually defined for the embedded language, but I think that is actually a shallow embedding. Looks like I can't correct my earlier comment.
Only the top level function has to be first order - you can use higher order functions within the body of your code.
Doesn't Haskell need automatic memory management in order to implement higher-order functions, that being perhaps the most prominent difference in semantics between Haskell/Ocaml and Rust? Is Clash limited to first-class functions ala C?