はじめに
checkForFactor :: Int -> Int -> Bool
checkForFactor = (.) (== 0) . mod
これをなんとか理解しました。
でも、微妙に納得いってない部分があったんですよね。
その答えがわかったので追記する形です。
問題
checkForFactor :: Int -> Int -> Bool
checkForFactor x y = (.) (== 0) (mod x) y
これが原型です。
-
mod x
でカリー化した1引数関数(定数xを割る、引数yの関数)を返す。 - 1の関数を、
(== 0)
と関数合成。 - これで、
y
を受け取る→mod x
によりx % y
が計算され、(== 0)
に渡される→真偽値が返る、という関数が作れました!
問題は、ここからの変形です。
前の記事ではごちゃごちゃ書きましたが……
解決方法
y
の削除
checkForFactor x y = (.) (== 0) (mod x) y -- 1
checkForFactor x = (.) (== 0) (mod x) -- 2
まずは基礎的にf x y = (.) g (h x) y
の時、f x = (.) g (h x)
です。
1
の式checkForFactor x y = (.) (== 0) (mod x) y
はつまりf x y = (.) g (h x) y
なので、
2
のcheckForFactor x = (.) (== 0) (mod x)
に変形できます。
x
の削除←ごちゃついたところ
checkForFactor x = (.) (== 0) (mod x) -- 2
checkForFactor x = ((.) (== 0)) (mod x) -- 3
checkForFactor = ((.) (== 0)) . mod -- 4
checkForFactor = (.) (== 0) . mod -- 5
まず、2
を3
に変形します。
すると、f x = g (h x)
の形になります。
f x = g (h x)
のとき、f = g . h
のため、
3
から4
checkForFactor = ((.) (== 0)) . mod
が成り立つのです!!
あとは、余分な()
を取り除いて、
5
のcheckForFactor = (.) (== 0) . mod
が導けます。
挙動は
-
x
を部分適用し、mod x
が生成される。 -
mod x
は(.) (== 0)
と合成され、「新しい関数」が生成される。 - 「新しい関数」は引数
y
を受け取り、x `mod` y
の結果が0
かどうか判定する。
終わりに
ChatGPT先生と協力して、Javascriptでコードを書いてみました。
checkForFactor = (.) (== 0) . mod
のロジック・挙動を模倣したものです。
//mod
function mod(x) {
return function (y) {
return x % y;
}
}
//(.) (== 0)
function dotEqZero(f) {
return function (x) {
return f(x) === 0;
}
}
//checkForFactor = (.) (== 0) . mod
function checkForFactor(x) {
return dotEqZero(mod(x))
}
checkForFactor(x)(y)
もやもやがすっきりするの、キモチイイ……
またひとつ強くなってしまった……( •´ω•` )ﻭカンチガイジャナイヨネ?
まあ、すぐ壁にぶつかるんですけどね。
ばらかもんのなるを思い出しますね。
「僕最強。見るものすべてが美しい」状態と、「えっ知らない無理無理 Σ(OωO )」を繰り返すんだと思います、きっと。