Haskell Learners' Group (Session 2)
By Walker Malling and Richard Cook, 2018/5/2

A recap of what we talked about during the second meeting of the Haskell Learners’ Group in Seattle

Introductions

We had about three additional attendees which was pretty nice. Most of last month’s attendees returned which was also very encouraging! We talked about the Slack channel and how there is been much lively and fun discussion. Walker set the tone for the meeting: functions, functions, functions!

Review

Richard briefly reviewed our last session, touching on the essentials of the haskell development environment and the anatomy of a Stack project. Refer to last month’s minutes!

In discussion regarding Stack, Richard also mentioned other build tools popular in the Haskell community, namely nix, and a new experimental tool called pier.

Functions

Richard worked from some of his Beginning Practical Haskell material on the subject of functions. Talking points included:

What is functional programming?

One possible answer: Programming that emphasizes functions over everything else

How do values and functions relate in Haskell?

One possible answer: Functions are values in Haskell; the converse is not necessarily true: not all values are also functions, though they certainly look (syntactically, at least) like nullary functions (functions in one argument)

Richard discussed visual elements of Haskell programs

Declarations

a = 5   -- is a declaration

a = 6   -- not a mutation, an instance of name shadowing (creating a new nested scope)

Richard Rodseth correctly mentioned that we should emphasize that declarations in Haskell are equations

Richard (Cook) valiantly tries to say “is” instead of “equals” and to avoid using the word “assign” altogether

Brief (but necessary!) Tangent on Types & Type Signatures

We considered the difference between a + 1 and a + 1.1.

a + 1.1 has type :: Fractional a => a

a + 1 has type :: Num a => a

We used the ghci :info command to inspect the Num and Fractional type classes.

:info Num and :info Fractional

(We duscussed the difference between a Type and a Typeclass…)

You can implement your own Num typeclass if you want, as long as you adhere to the requirements of the typeclass properties, e.g. you implement all its methods

Introduction to concrete vs. polymorphic types

Note on the difference between Haskell and other languages: Haskell’s typeclasses are unlike Java interfaces and abstract classes (which are dynamic dispatches at runtime; typeclasses are resolved at compile time)

Fucntions, take 2 (return from tangent on types!)

Function Arguments

Function declarations declare one or more arguments identified by name on the left-hand side of the equation

All Haskell functions are actually functions in one argument and multiple arguments in declarations are syntactic sugar

We breifly discussed currying (all Haskell functions are automatically curried)

We Talked about parentheses and how Haskell can simulate “parentheses” languages using tuples

Richard also mentioned CodeWorld’s “parentheses” variant of Haskell

Simple functions

add or addIntegers for adding numbers

add x y = x + y is the same as add = \x y = x + y

You can (and we did) prove that by getting the type signature of each in ghci.

“Applying f to x” looks like this is Haskell: f x y

Pedagogical notes: At this point we got sidetracked by a discussion on Num and related type classes. It might make sense in the future to introduce fully monomorphic functions at first to avoid being sidetracked by type variables and type classes. The problem there is teh lack of sensible monomorphic functions. All common arithmetic operations and functions are defined in terms of Num, Fractional, Floating etc. Perhaps use a custom simplified prelude? Even strings are problematic, as we then have to deal with lists and explain that String and [Char] are equivalent

We talked about name shadowing particularly in GHCi

Pedagogical notes: This is confusing especially given the immutability of Haskell variables. Of course, immutability is one of Haskell’s primary selling points, so some thought needs to go into how to teach this

Richard stated that accessing shadowed names is possible but couldn’t remember how; Jake reported back how to do it (see)

Richard Introduced following function concepts

Lists

Richard demonstrated the basics of lists, included the range opeartor ..

Mentioned also that any type with an Enum instance can be used to define a range.

We determined that [False..True] doesn’t parse but [False .. True] does (conflicts with qualified name syntax)

Started talking about generating lists of days of the month

More Notes on a Haskell program:

“Haskell lifehacks” vol 1

Building in loop with file watcher

stack build --file-watch --exec hello-seattle

Where hello-seattle is the binary (the name of the stack project).

Finding symbols

Danielle asked: how do you identify which imported module is failing when writing a program

You can use :info to see all the places the module is referenced, and where the symbol is defined

More questions about IDE integration (i.e., for automatically importing libraries) and import lists

The style of import statements can affect discoverability of symbols

Explicit imports (e.g. import Data.List (intercalate)) make it very clear where a given symbol comes from… but they’re kinda noisy and verbose

IDE tooling could help with keeping these lists under control and the compiler can warn about unused imports

Can search using Haskell.org Hoogle and Stackage Hoogle

Can also install Hoogle locally (ask Richard about his GHCi :hoogle command if you want more information)

Hoogle supports search by symbol as well as search by type signature

“Haskell Lifehacks” vol 2

You can set a custom search engine in Chrome and bind it to a key of your choosing, such that when the address bar is in focus, hitting h (for example) will activate hackage.haskell.org, and anything you enter into the address bar thereafter will by piped into the hackage search engine.

You can (reputedly) do this with Firefox as well, but this was not demostrated.

Month Exercise

Jake suggested we try an exercise:

Implement a function datesInMonth :: String -> Int -> [String] which takes the name of a month (“May”) and the number of days in that month (31), and returns a list of all the dates in that month (["May 1", ..., "May 31"]).

Richard did some live coding, until we hit 8pm and had to take the show on the road.

Projects

There was some brief discussion as we were leaving of appropriate projects or outcomes from these meetings. Walker and Richard hope to present something appealing to all attendees shortly!