8

私は単純なツリー構造を持っています:

data Tree a = Leaf | Node a (Tree a) (Tree a)

そしてFoldableの実装:

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

4

1 に答える 1

9

タイプを調べてみるとfoldMap

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

unbound type があることがわかりますm。通常、これが発生する場合、それは何でもmあり得ることを意味しますが、ここでは も制約します。そこから来ています。mMonoid mMonoid

インスタンスがない場合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を使用するため、型はそれを反映しています。最も一般的なタイプは、Monoidexpr

expr :: Monoid m => m -> m

ここでも、somemに制約された自由型変数です。 Monoid


関数foldMapを使用できる理由は、その型シグネチャで可能な種類を明示的に制限するためです。そこに制約を置くことで、それらを操作する力が増します。Monoidm

于 2013-11-08T01:51:47.187 に答える