This page titled, “What I wish I knew when learning Haskell” has this interesting section on monads. I agree with his statement that there’s no sense in studying monads; you just need to write a lot of FP code, and then you’ll see when you need a monad. That is, studying monads is like studying OOP design patterns when you don’t need them; they’re interesting to learn, but until you need them and use them you won’t really understand them.
Posts in the “haskell” category
I’m currently trying to cram Haskell into my brain, and in an effort to do so, I’ve been writing a fake POS (point of sales) application. It has a command-line UI that prompts the user to add
Pizzas and a
Customer to an
I need to re-organize the code, but this is what about 50% of the code looks like right now. The other 50% is in a module that defines what a
Pizza is, and also defines its helper functions.
“If it wasn’t for the problem of how to sequence input-output actions correctly, monads probably wouldn’t have appeared in Haskell. But once it was appreciated what they could do, all kinds of other uses quickly followed.”
~ Thinking Functionally with Haskell, Richard Bird
putStrLn doesn’t print to standard out, it returns a value — of type
IO () — which describes how to print to standard out, but stops short of actually doing it.”
From the article, An IO Monad for Cats.
I was working on a Haskell factorial function (which turned out to be easy) and decided I wanted to write a program to prompt a user at the command line for an
Int, and then do the factorial of that
I quickly learned that this required a
Int conversion, which I wanted to do safely (I didn’t want my program to blow up). Technically what I do is actually a
Maybe Int conversion, as you can see in this code:
As a quick note to self, this source code from the online version of Learn You a Haskell shows how to read command line arguments in Haskell:
-- from "Learn You a Haskell" -- http://learnyouahaskell.com/input-and-output import System.Environment import Data.List main = do args <- getArgs -- IO [String] progName <- getProgName -- IO String putStrLn "The arguments are:" mapM putStrLn args putStrLn "The program name is:" putStrLn progName
If you save that source code in a file named args.hs, and then compile it with ghc like this:
you can test it with no command line args like this:
$ ./args The arguments are: The program name is: CommandLineArgs
and then give it a few test command line args like this:
$ ./args foo bar The arguments are: foo bar The program name is: CommandLineArgs
As I show in the comments that I added,
getArgs has the type
IO [String], and
progName has the type
I want to try writing a few simple scripts/programs in Haskell, so hopefully over time I’ll add more information on how to process command line arguments in Haskell. Until then, the Learn You a Haskell link I shared at the beginning has good information on handling I/O in Haskell.
“How to write ‘Hello, world’ in Haskell.” This was even more humorous this morning when I saw it shared on Twitter by someone who is recruiting Haskell developers.
If you need to have multiple types extend a base type in Haskell, while using the
data keyword, and while using Haskell’s record syntax, this approach seems to work:
A fun thing about looking at different programming languages is that you get to see the unique features of each language. For instance, some people don’t like Lisp because of all of the parentheses, and then Haskell seems to counter that by saying, “Hey, here are a couple of ways to get rid of parentheses.”
Haskell’s $ operator
One of the approaches Haskell uses is the
$ function, which is called the function application operator. As an example of how it works, imagine that you want to calculate the square root of three numbers. This first approach is intentionally wrong because it calculates the square root of 3, then adds that to 4, then adds that to 2:
let x = sqrt 3 + 4 + 2 # intentionally wrong
The usual way to correct this is with parentheses: you need to make sure the three numbers are added together first, before the
sqrt function is applied. As with other programming languages, Haskell lets you write this:
let x = sqrt (3 + 4 + 2)
For the first 20+ years of my programming life I wrote code like that, but Haskell says, “You know what, those parentheses are kind of noisy, let’s get rid of them.” The way you get rid of them is by using
let x = sqrt $ 3 + 4 + 2
Whoa, that’s different.
The first 50 or 100 times you see that it’s pretty freaky, but over time it grows on you. As the book, Learn You a Haskell for Great Good states, you can think of
$ as being like an “open parenthesis.”
Comparing parentheses to $
$ is a little more attractive when you compare it to the same expression that uses parentheses. For instance, these two lines are equivalent, and the second line is a little easier on the eyes:
sum (map sqrt[1..10]) sum $ map sqrt[1..10]
The same is true of these two lines of code:
putStr (map toUpper "rocky raccoon") putStr $ map toUpper "rocky raccoon"
Until I saw this approach, I never realized how much noise parentheses add to an expression.
Read from right to left
Here’s one more example:
let x = negate(sqrt(3 + 4 + 2)) let x = negate $ sqrt $ 3 + 4 + 2
With an expression like this, you basically read the code from right to left. That last line can be read like this:
Sum up “3 + 4 + 2” // 9
Take the square root of that // 3
Negate that value // -3
Bind that result to x // x = -3
Because of the way it works, we say that
$ is right-associative.
At the moment I don’t know how the Haskell creators came up with the
$symbol. When I read code like this it reminds me of reading Unix command pipelines, except that you read them from right to left. That makes me think that the
|symbol would have been cool here.
I don’t have a major summary here, I just wanted to show a few examples of how to use Haskell’s
$ operator (which is technically a function). The
$ in Haskell has at least one more use that I’m aware of, and I’ll try to write about that at some point.
(Note: The examples on this page were inspired by the book, Learn You a Haskell for Great Good.)
Simon Peyton Jones, writing about “Respect” in the Haskell community. For the rest of his post, see this mail.haskell.org link.
“Purity makes the job of understanding code easier.”
This image of “lessons learned” comes from an article titled, “Learning FP the hard way: Experiences on the Elm language.” (Elm is incredibly similar to Haskell.)
“You know, Haskell actually never liked the name Haskell.”
~ Mrs. Haskell Curry
“As soon as you start programming with side effects, evaluation order becomes important.”
“Side effects are essentially invisible inputs to, or outputs from, functions.”
I was curious about how the “input redirection” program on page 170 of Learn You a Haskell for Great Good (LYAH) worked, so I typed it into a file named do1.hs, with one additional line:
import Data.Char main = do contents <- getContents putStrLn "dude" putStr $ map toUpper contents
The line I added is the
putStrLn "dude" line.
I compiled it like this:
This image comes from an article titled, A founder’s perspective on four years with Haskell. I appreciate his honesty about the Haskell ecosystem. I remember wanting to use Haskell for some JSON parsing, and when I looked around for a Haskell/JSON library, all I could find was some tutorials on how to build your own.
“Functional programming is all about putting data first. We think about what kinds of data we have in a problem domain, and what kinds of transformations we want on them. Then we start building up the data structures and the code to do the transformations.”
“Haskell is a lazy language: any given piece of data is only evaluated when its value must be known.” (From Real World Haskell.)