Haskellでいろいろ遊んでみる

初心者向けテーマとして、ブラックジャックが面白い、らしいので、Haskellで作成してみました。

https://qiita.com/KNaito/items/385fb1701f70ffb8ffd4

で、Qiitaの記事には完成したものしか書いてないのですが、そもそも自分が普通のプログラミング(いわゆる手続き指向型プログラミング)思考になっているため、本当に基本的なことでつまづきまくりました。

例えば、整数を2で割った値を返し、1の場合は1を返す次のような関数を定義してみます。


func :: Int -> Int
func 1 = 1
func x = x `div` 2

Haskellに慣れていない人のために、JavaScriptで書くとこれは


function func(x) {
if (x==1) return 1;
return Math.floor(x/2);
}

こんな感じ。

でもって、これを呼び出すときに


main :: IO ()
main = do
let x = 10
let y = func x
print y

と呼び出せば、期待通り10を2で割った5が表示されるのですが、変数の名前を節約したいと思って


main :: IO ()
main = do
let x = 10
let x = func x
print x

としてしまうと、無限ループしてしまいます、、。

理由は多分、print xの段階で遅延評価がはじまり、そこでx = func xの右辺を計算しようと
するのですが、右辺のxは、結局同じ式のx = func xで定義されているので、x = func func x
となっていまい、そのまた右辺のxを計算しようとして、x = func func func x ...と無限ループ
してしまうようです。

数学的には