Build Haskell stuff in your browser

2019-02-13

tl;dr

What’s an online REPL?

In case you don’t already know, there has been a surge of online programming environments in recent years, most notably interactive notebooks and REPLs. This stuff is really popular the webdev and data science communities2.

The idea is that you can type in some commands, have them executed by whatever interpreter, write code in files/modules, build interactive programs, create visualizations, entire websites, and so on.

Here are the major examples I can think of for various languages:

That last one is what this post is about. Repl.it is great for many reasons, not least because it started providing a Haskell environment two years ago.

sidenote: repl.it has this feature where multiple people can join the same editor and all edit at the same time, which is insanely cool. Get some friends and click the “multiplayer” button.

The libraries nobody told you about

Unfortunately it’s not clear which packages apart from base are built in. Random guessing quickly shows that at least containers and text are available, but I couldn’t find a complete list anywhere. Of course we won’t let that stop us. After a bit of fiddling and exploring:

:! ls -l /opt/ghc/8.6.3/lib/ghc-8.6.3/

:! ghc-pkg list5

Explanation: :! is a ghci command6 that lets you execute whatever you want in the shell.

We can see that we have access to the following7 libraries:

/opt/ghc/8.6.3/lib/ghc-8.6.3/package.conf.d
    Cabal-2.4.0.1
    array-0.5.3.0
    base-4.12.0.0
    binary-0.8.6.0
    bytestring-0.10.8.2
    containers-0.6.0.1
    deepseq-1.4.4.0
    directory-1.3.3.0
    filepath-1.4.2.1
    (ghc-8.6.3)
    ghc-boot-8.6.3
    ghc-boot-th-8.6.3
    ghc-compact-0.1.0.0
    ghc-heap-8.6.3
    ghc-prim-0.5.3
    ghci-8.6.3
    haskeline-0.7.4.3
    hpc-0.6.0.3
    integer-gmp-1.0.2.0
    libiserv-8.6.3
    mtl-2.2.2
    parsec-3.1.13.0
    pretty-1.1.3.6
    process-1.6.3.0
    rts-1.0
    stm-2.5.0.0
    template-haskell-2.14.0.0
    terminfo-0.4.1.2
    text-1.2.3.1
    time-1.8.0.2
    transformers-0.5.5.0
    unix-2.7.2.2
    xhtml-3000.2.2.1

FUN. I don’t know about you, but at this point I get pretty excited, since this means that we can write a lot more serious stuff than I had initially realized.

For example, we can write entire interactive command-line programs that repl.it will automatically serve up at https://[replname].[username].repl.run. Here you can play with an example I simply copy-pasted from the haskeline documentation.

If you’re not familiar with the libraries above, here’s an (incomplete) overview:

That’s it for now, figure out the other libraries yourself. It would obviously be great to have more. For example to have wreq to make network requests, or some graphics package to create images or draw on the DOM.

With enough interest repl.it might be persuaded to include more packages. Before discovering all this, I messaged them on their twitter to ask if they could update GHC from 8.0.x to 8.6.3 in the coming year, and they literally did it within an afternoon. Amazing.

What now?

Now that you have no more excuses, I guess you just have to go and build stuff. If you’re a newbie, then work through the exercises from Haskell Programming from first principles (paid, but very worth it), or Learn You a Haskell (free and utterly charming).

Use haskeline and go write a clone of Zork. Do whatever! Share what you make on r/haskell, and come ask questions in the #haskell channel on the functional programming discord.

Here is a code snippet so that you don’t get bored in the meantime. Save it into a new file in repl.it, hit run and load up the module with something like :l Entropy.hs.

Do you have the right intuition for what has high or low entropy? I didn’t.

{-# LANGUAGE ScopedTypeVariables #-}

module Entropy where

import           Data.Map.Strict (Map)
import qualified Data.Map.Strict as M

-- tally the number of occurrences of all the items in a list:
count :: forall a . Ord a => [a] -> Map a Int
count elements =
    foldl addCount M.empty elements
    where
        addCount :: Map a Int -> a -> Map a Int
        addCount counter el = M.insertWith (+) el 1 counter

-- calculate which element occurs which percentage of the time
proportions :: Ord a => [a] -> [Double]
proportions xs =
    [c / n | c' <- counts, let c = fromIntegral c']
    where
        counts = M.elems (count xs)

        n = fromIntegral $ length xs

-- entropy measure
-- https://en.wikipedia.org/wiki/Entropy#Statistical_mechanics
entropy :: Ord a => [a] -> Double
entropy xs =
    -sum [p * logBase 2 p | p <- proportions xs]

  1. Your main function will be run in a little pseudo-terminal, so all your dumb adorable little putStrLn and getLine will print text or wait for user input. You can’t pass arguments or flags to your program tough, since you don’t control stdin. It has to be interactive with something like getLine. [return]
  2. I was skeptical of online programming environments at first, since the idea sounds a bit gimmicky. I changed my mind8 after seeing how many children build really impressive things in them, and how joyful it feels to use one for quick demos and experiments. It’s really easy to send somebody a code snippet that just executes, zero friction. Beginners can still install stack or cabal afterwards, no rush. [return]
  3. We also have our very own Haskell Kernel currently maintained by total champion Vaibhav Sagar. It’s all there, but more help is needed to remove some frictions for beginners, like a noob-friendly install experience and more cool tutorials. EDIT: I’m being informed on reddit that you can actually use IHaskell online. [return]
  4. Get it? JuPytR! [return]
  5. I didn’t know about ghc-pkg list, but my friend Nicolas did. [return]
  6. I came across this in a list of all ghci commands, hoping for one that lists all importable modules for a specific ghci session. [return]
  7. Why precisely those? Turns out they are probably just the core packages that GHC ships with. Again, thanks Nicolas! [return]
  8. meta-footnote: Come to think of it, it was actually https://tryhaskell.org/ that first exposed me to Haskell and made me so excited about it. [return]
~
hi there, well done with the scrolling! nothing more to see here. the blank space is so that jumping to footnotes doesn't suck.