[英]Folding without Monoid instance
我有一個簡單的樹結構:
data Tree a = Leaf | Node a (Tree a) (Tree a)
還有一個可折疊的實現:
import qualified Data.Foldable as F
instance F.Foldable Tree where
foldMap f Leaf = mempty
foldMap f (Node x l r) = F.foldMap f l `mappend`
f x `mappend`
F.foldMap f r
即使沒有Monoid
的實現,它仍然有效,我不能在我的代碼中使用mappend
和mempty
。 那么這個Foldable
實現如何工作?
如果檢查foldMap
的類型
class Foldable f where
foldMap :: Monoid m => (a -> m) -> f a -> m
你會看到它有一個未綁定的類型m
。 通常,當這種情況發生時這意味着m
可以是任何東西 ,但在這里它也限制m
與Monoid m
。 那就是Monoid
來自。
值得注意的是,如果我們沒有Monoid
實例,那么很難定義一個返回“可能是任何東西”的值的函數。 如果你嘗試它,你會發現它幾乎是不可能的(沒有“作弊”)。
impossible :: Int -> b -- no constraints on `b` at all!
impossible i = ...?
但如果我們對這種類型有所了解,那就很容易了
veryPossible :: Num b => Int -> b
veryPossible i = fromIntegral i
-- or
veryPossible2 i = fromIntegral (i * i) + fromIntegral i
作為另一個例子,考慮表達式的類型
expr m = mconcat [m <> m <> mempty, mempty <> m]
因為這個表達式是基於一些未知值m
構建的,並且只使用Monoid
類中的函數或它們的派生類,所以它的類型反映了這一點。 最常見的expr
類型是
expr :: Monoid m => m -> m
在這里, m
是一個自由類型變量,被約束為一些 Monoid
。
foldMap
允許你使用Monoid
函數的原因是因為它明確地約束了類型簽名中的m
類型。 通過設置約束,我們可以獲得更多操縱它們的能力。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.