首先让我道歉,但我根本找不到我的答案 问题,虽然我很确定之前已经问过这个问题。现在:
我想为二进制(搜索)编写Functor
和Monad
个实例
树。更准确地说,insert
或merge
等一些功能需要
Ord
的实例,例如:
data Tree a = Empty | Node a (Tree a) (Tree a)
insert :: (Ord a) => Tree a -> a -> Tree a
merge :: (Ord a) => Tree a -> Tree a -> Tree a
因此,以下代码无法编译:
instance Monad Tree where
{- ... -}
Empty >>= f = Empty
(Node v l r) >>= f = merge (f v) (merge newL newR)
where newL = l >>= f
newR = r >>= f
-- No instance for (Ord b) arising from a use of `merge'...
由于我不知道更好,我已经尝试在声明上声明Ord
约束
ADT使用DatatypeContexts
,但已被弃用且无论如何都无效。其他
像FlexibleInstances
之类的扩展等在我意识到之前似乎都很有用
真的意味着别的什么。
那么,有没有办法,我该怎么做呢?谢谢你的时间。
编辑:同时我发现这个有用answer,但看起来好像为Functor
这样的类型类做这样的东西仍然是一个问题。
答案 0 :(得分:4)
有多种方法可以做到这一点,但没有一种方法可以完全清洁。
你应该查看的关键术语是“受限制的monad”。
这是rmonad
包的一个例子(我写的)。
{-# LANGUAGE NoImplicitPrelude, TypeFamilies, GADTs,
FlexibleInstances, MultiParamTypeClasses #-}
import Control.RMonad.Prelude
import Data.Suitable
data Tree a = Empty | Node a (Tree a) (Tree a)
insert :: (Ord a) => Tree a -> a -> Tree a
insert = undefined
merge :: (Ord a) => Tree a -> Tree a -> Tree a
merge = undefined
data instance Constraints Tree a where
TreeConstraints :: Ord a => Constraints Tree a
instance Ord a => Suitable Tree a where
constraints = TreeConstraints
instance RFunctor Tree where
fmap f Empty = Empty
fmap f (Node v l r) = Node (f v) (fmap f l) (fmap f r)
instance RMonad Tree where
{- ... -}
Empty >>= f = Empty
(Node v l r) >>= f = withResConstraints $ \TreeConstraints ->
merge (f v) (merge newL newR)
where newL = l >>= f
newR = r >>= f
请参阅包here的一般文档。
请注意,RMonad
是与Monad
不同的类型类。如果您想拥有一个真实的Monad
实例,可以使用AsMonad Tree
。