使用具有约束类型的方法的类型类实例

时间:2014-01-09 06:44:42

标签: haskell constraints typeclass

首先让我道歉,但我根本找不到我的答案 问题,虽然我很确定之前已经问过这个问题。现在:

我想为二进制(搜索)编写FunctorMonad个实例 树。更准确地说,insertmerge等一些功能需要 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这样的类型类做这样的东西仍然是一个问题。

1 个答案:

答案 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