Tôi đang học Haskell và đang thực hiện một chương trình DB-seed đơn giản cho Yesod khi tôi tình cờ thấy hành vi này mà tôi thấy khó hiểu:
testFn :: Int -> Bool -> [Int]
testFn a b = if b then replicate 10 a else []
Phiên YesHC 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]
Bằng cách nào đó, nó có thể "rút" ra "Bool" thứ hai từ mỗi ánh xạ thành một đối số được quấy rối.
Phiên bản cơ sở chuẩn Prelude GHCI từ chối biên dịch biểu thức này:
$ :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]
Hóa ra Yesod sử dụng thư viện truyền tải đơn âm có cái riêng concatMap
:
$ :t concatMap
concatMap
:: (MonoFoldable mono, Monoid m) =>
(Element mono -> m) -> mono -> m
Ở cấp độ hiểu biết về Haskell hiện tại của tôi, tôi không thể tìm ra cách các loại được phân phối ở đây. Ai đó có thể giải thích cho tôi (càng nhiều người mới bắt đầu định hướng càng tốt) làm thế nào thủ thuật này được thực hiện? Phần nào testFn
ở trên là phù hợp với Element mono
loại?