私はHaskellを学んでいて、理解しにくいこの動作に出くわしたときに、Yesodのために単純なDBシードプログラムを実行していました。
testFn :: Int -> Bool -> [Int]
testFn a b = if b then replicate 10 a else []
Yesod GHCIセッション:
$ :t concatMap testFn [3]
concatMap testFn [3] :: Bool -> [Int]
$ (concatMap testFn [1,2,3]) True
[1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3]
どういうわけか、各マッピングからその2番目の「ブール値」を単一のカレー引数に「引き出す」ことができました。
標準ベースのプレリュードGHCIセッションでは、この式のコンパイルも拒否されます。
$ :t concatMap testFn [3]
error:
• Couldn't match type 'Bool -> [Int]' with '[b]'
Expected type: Int -> [b]
Actual type: Int -> Bool -> [Int]
• Probable cause: 'testFn' is applied to too few arguments
In the first argument of 'concatMap', namely 'testFn'
In the expression: concatMap testFn [3]
Yesod は、独自の独自の横断可能なライブラリを使用していることがわかりましたconcatMap
。
$ :t concatMap
concatMap
:: (MonoFoldable mono, Monoid m) =>
(Element mono -> m) -> mono -> m
現在のHaskell理解のレベルでは、ここで型がどのように分散されているのか理解できませんでした。誰かが私に(できるだけ多くの初心者向け)このトリックがどのように行われるか説明できますか?testFn
上記のどの部分がElement mono
タイプに準拠していますか?