下午好,我正在嘗試寫一個 RB 樹幺半群,代碼是這樣的:
data Tree a = Leaf | Node a Color (Tree a) (Tree a) deriving (Show)
instance (Ord a) => Monoid (Tree a) where
mempty = Leaf
l1 `mappend` l2 = foldl (\x y ->insert y x) l1 l2
instance Foldable Tree where
foldr _ z Leaf = z
foldr f z (Node d _ l r) = foldr f (f d (foldr f z r)) l
foldl _ z Leaf = z
foldl f z (Node d _ l r) = foldl f (f (foldl f z l) d) r
...
insert :: (Ord a) => a -> Tree a -> Tree a
insert x s = makeBlack $ ins s
where ins Leaf = Node x Red Leaf Leaf
ins (Node d c l r)
| x < d = balance d c (ins l) r
| x == d = Node d c l r
| x > d = balance d c l (ins r)
makeBlack (Node d _ l r) = Node d Black l r
問題是幺半群的宣告:
? Could not deduce (Semigroup (Tree a)) arising from the superclasses of an instance declaration from the context: Ord a bound by the instance declaration at src/RedBlackTree.hs:19:10-35 ?
In the instance declaration for ‘Monoid (Tree a)’ | 19 | instance (Ord a) => Monoid (Tree a) where | ^^^^^^^^^^^^^^^^^^^^^^^^^^
我知道為了使用insert這些值必須是可比較的,但似乎我(Ord a)在實體中以某種方式誤導了
獎金問題:我也實施fmap了,但不明白與foldMap
uj5u.com熱心網友回復:
這不是Ord問題所在。如果您仔細查看收到的錯誤訊息,它以“Could not deduce (Semigroup (Tree a)) arising from the superclasses of an instance declaration”開頭。換句話說,為了擁有 的實體Monoid (Tree a),您需要首先擁有 的實體Semigroup (Tree a)。幸運的是,這很容易添加:
instance (Ord a) => Semigroup (Tree a) where
(<>) = mappend
(也許更慣用的方法是<>在Semigroup實體中使用foldl您使用的定義來定義 for mappend,然后在您的實體中 for Monoid,只需省略 的定義mappend。)
fmap獎勵:和之間的區別foldMap從它們的型別中就很明顯了。對于您的樹,fmap將具有型別(a -> b) -> Tree a -> Tree b,表明它正在將內部a值映射到b值。另一方面,foldMap會有型別Monoid m => (a -> m) -> Tree a -> m. 您可以選擇呼叫foldMapwith m ~ Tree b,在這種情況下foldMap變得非常類似于fmap(型別將是(a -> Tree b) -> Tree a -> Tree b,這與 不完全相同fmap),但您也可以選擇呼叫它 withm ~ [b]或其他一些幺半群。(感謝@amalloy 和@Daniel Wagner 的評論。)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/537525.html
標籤:哈斯克尔
上一篇:多個變數被識別為決議錯誤
