簡體   English   中英

沒有Monoid實例的折疊

[英]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的實現,它仍然有效,我不能在我的代碼中使用mappendmempty 那么這個Foldable實現如何工作?

如果檢查foldMap的類型

class Foldable f where
  foldMap :: Monoid m => (a -> m) -> f a -> m

你會看到它有一個未綁定的類型m 通常,當這種情況發生時這意味着m可以是任何東西 ,但在這里它也限制mMonoid 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM