Posted at

Haskell の勉強会を開いてみたら色々気づきがあったのでメモ


はじめに

先日(2018-12-09)、友達を集めてプログラミング Haskellをみんなで勉強しようという勉強会を開きました。

基本的にもくもく会のスタイルで、詰まったりわかんなかったら相談、という流れです。

ぼくを除いて Haskell 未経験者で、処理系のインストールからやった人も居たのですが、 Haskell そのものから外れた部分でちょっとした気づきがあったのでメモします。


参加者

参加者は全員異なるバックグラウンドの人でしたが、

全員 IT の基本的なスキルはある人でした。

エディタも Atom, Visual Studio, Emacs などなどバラバラでした。


A

ぼくです。大学に居た頃にプログラミング Haskell をひとおり勉強しました。

大学を出てからは特に使うこともなく、時折遊んでみる位だったのですが、最近またやってみたくなったので定期的に勉強会に出ています。


B

普段は MATLAB で信号処理の計算をしている人。

最近 MATLAB の Lambda 式にハマって色々使っているので、 Haskell に興味を持ったとか。


C

PHP でバリバリ色々作ってる人。最近は革の盾を作っている。


D

インダストリアル・エンジニアリングの人。オペレーションズ・リサーチにも興味があるらしい。業務を圏論で書き下せないかみたいな事を言っていたので、ぼくが Haskell を教えたら勉強会開くながれになった。


E

インフラ中心に色々やってたけど、最近はコンサルとかディレクションに移行しつつある人。自分の武器を増やしたいので参加したそうな。


Stack


Mac の場合

参加者に Mac ユーザが二人居て、

どちらも stack

GHC をインストールをしました。

stack から GHC をインストールするには gcc が必要になるので、

XCode をインストールしておく必要があります。

あと、 stack 最初に GHC が無いと動かなかったりする?ので、

brew あたりから別途入れといたほうがいいかも。


Windows Defender に注意

参加者の一人は Windows 10 ユーザでした。

stack から GHC インストールしていたのですが、

Windows Defender をオンにしたところ、 stack がマルウェアとして削除されてしまったとのこと。

僕も Windows 10 で WSL から stack で使っていても同じ現象が起きてないのですが、そういうこともあるようです。


Haskell


GHCi は GHC でコンパイルする場合とは多少挙動が近いので注意

GHCi 上からパターンマッチで関数定義をすると、そのままだと上手くいかない現象がありました。

こんな関数を定義するとしましょう。

mysum [] = 0

mysum (x:xs) = x + mysum xs

このとき、これを ghci にそのままコピーして入力しても、

mysum は正しく定義されません。

なぜなら、二行目の定義で一行目の定義が上書きされてしまうからです。

この事は以下の一連の入力をすると確認できるでしょう。

x = 1

x
x = 2
x

x の値が変化することが見て取れるます。

複数行に渡る関数定義を行いたい場合は、

ghci の multiline command 機能を利用して以下のように記述します。

:{

mysum [] = 0
mysum (x:xs) = x + mysum xs
:}

この機能は以前の ghci には無かった(let を使わないと定義できなかった)気がするので、戻ってきた人はハマりやすい気がします。


-1 の取り扱い

ghci 上で関数の引数に -1 をそのまま渡すと、以下のようにエラーが出てしまいます。

Prelude> func x = x + 1

Prelude> func -1

<interactive>:10:1: error:
• Non type-variable argument in the constraint: Num (a -> a)
(Use FlexibleContexts to permit this)
• When checking the inferred type
it :: forall a. (Num a, Num (a -> a)) => a -> a

これを避けるためには、 "()" や "$" を使う必要があります。

Prelude> func (-1)

0
Prelude> func $ -1
0

この原因は "-" 自体が演算子であるためです。

これに関する議論は以下の記事に記載されています。

get rid of unary '-' operator

https://prime.haskell.org/wiki/NegativeSyntax