The Hazy Haskell Compiler

Are you sure you can free an STRef when you leave the runST? You can hide an STRef in an existential (if you have those) and smuggle it out. You can’t do anything very interesting with it, but it is reachable.

1 Like

I’m looking forward to running some code soon then.

1 Like

The only thing you can with an STRef without the the state token is compare them for equality and it shouldn’t be an issue to compare dead pointers for equality if they never move. It’s impossible to compare dead pointer to live ones too because the s parameters have to be the same in the Eq instance. I am a bit worried that LLVM or some other C optimizer would freak out if it saw dead pointer comparisons though.

Small update. I implemented putStrLn (and Text.pack, Text.putStrLn) so now this example works.

module Main where

type Peano :: *
data Peano = Zero | Succ Peano

length :: Peano -> String
length (Succ peano) = '+' : length peano
length Zero = ""

class Double a where
  double :: a -> a

instance Double Peano where
  double (Succ peano) = Succ (Succ (double peano))
  double Zero = Zero

quadruple :: (Double a) => a -> a
quadruple peano = double (double peano)

three, twelve :: Peano
three = Succ (Succ (Succ Zero))
twelve = quadruple three

main :: IO ()
main = putStrLn (length twelve)

Here’s is what the generated code looks like: Peano.js - Pastebin.com

Also, this is in already Readme, but let me reiterate the process of generating this.

$ cp -R runtime/ output
$ cabal run hazy -- -I library/runtime/ library/base -o output
Configuration is affected by the following files:
- cabal.project
$ cabal run hazy -- -I library/runtime/ -I library/base/ Peano.hs -o output
Configuration is affected by the following files:
- cabal.project
$ esbuild output/index.mjs --bundle --format=esm --platform=node --outfile=Peano.js

  Peano.js  4.6kb

Done in 13ms
$ node Peano.js
++++++++++++
$
10 Likes

Today is my birthday and I’d figure I would celebrate by giving a progress report on Hazy.

Here’s a quick list of what I’ve done over these past 3 months

  • Syntax sugar
    • Lambda expressions
    • Case expressions
    • Lambda case expressions
    • Let pattern binding
    • Integer literals
    • Floating point literals
    • Do notation
    • Right sections
    • Type annotation expressions
  • Language features
    • Default methods
    • Monomorphic generalization
    • Newtypes
    • Strict fields
  • Library / Tooling
    • A significant part of the Prelude has been implemented
    • A bare minimum package format for saving and loading sets of modules

I also have another new extension: LevityPolymorphicFields. You can now parameterize a field by it’s strictness.

type List :: Levity -> Type -> Type
data List s a
  = Nil
  | Cons
      { head :: ~!s a,
        tail :: ~!s (List s a)
      }

Here List Strict a would be a fully strict list while List Lazy a would be a lazy one. I have more details in my readme.

Of course all of this isn’t enough for Hazy to be usable yet as there’s still some missing parts, but I am getting a lot closer.

15 Likes

Why is the arrow naked here? I’d expect either a new arrow or some other syntax.

Naked, my System F brain sees no reason Levity affects other args here. I don’t like that. System F is the north star.

you seem to pass it along..but not in a meaningful. dependent way. You’re close (the extension is a good idea) but no cigar.

Highly recommend being brave enough to submit this to ghc-proposals`. That’ll ensure it passes bona fide muster.

I wonder, is the Levity attached to the arrow? In Coalton they attached * to the arrow, like “Int * Char → Int,” or “Int → Char * Text”. I.e one can give multiple inputs and output multiple outputs for a function, but there isn’t a free-standing “a*b”. I find this really neat in a strict language like Coalton. (PureScript has a less neat mechanism, but similar idea.)

1 Like

I wonder, is the Levity attached to the arrow?

Well, I did make this post: Levity should be on the arrow, not on the kind. So far I only implemented levity polymorphic fields and not levity polymorphic arrows, but it’s something I plan on doing eventually.

I also have a post on this: Levity should be on the arrow, not on the kind - #35 by superstar64. If you have levity on the arrow in system-f, then these levity polymorphic fields appear in scott encoding.

1 Like

Happy belated birthday!!!

1 Like

Let me post another update. I’ve implemented the following:

  • Binding groups
    • Global generalization (across mutually recursive modules too)
    • Local generalization
  • List comprehensions
  • Prefix negation
  • Record updates

Hazy is now at the point where nearly all of Haskell 2010’s language features work. The main missing feature now is deriving. There are these deficiencies that I need to fix too:

  • Contained type variables are not generalizated
  • Constraints are limited to unique type class / type variable pairs
  • Some missing builtin instances
  • Other small issues

Lastly, these are the language features. Almost none of Hazy’s base is implemented.

13 Likes