2015-01-15 91 views
3

我想写:约束实例方法

{-# LANGUAGE InstanceSigs #-} 
{-# LANGUAGE DatatypeContexts #-} 

data Ord a => S a = ... 
toList :: Ord a => S a -> [a] 
fromList :: Ord a => [a] -> S a 

instance Functor S where 
    fmap :: (Ord a, Ord b) => (a -> b) -> S a -> S b 
    fmap f = fromList . fmap f . toList 

但GHC一直嫌我失望

方法签名不匹配类

问题:

  • 你知道解决方法吗? ?
  • 这个限制解决了什么问题?
+5

ghc警告:-XDatatypeContexts已被弃用:它被广泛认为是一种错误,并已从Haskell语言中删除。 – ErikR

+0

@ user5402为什么呢?你会做什么呢? –

+2

@MichaelFox一个GADT,比如's S,其中S :: Ord a => [a] - > S a',或者任何你的构造函数。 – bheklilr

回答

5

你不能,简单地说。 Functor类定义为它必须与所有a -> b一起使用,而不仅仅是一些a -> b。不过,您可以定义自己的FunctorOrd

class FunctorOrd f where 
    fmapOrd :: (Ord a, Ord b) => (a -> b) -> f a -> f b 

但是,这可能不是你想要的。我猜你想创建一种类似于集合的结构,在内部使用二叉树来保持唯一性。如果我这样做

s :: S Int 
s = fromList [1..100] 

t :: S Bool 
t = fmap even s 

这只是在设置应用evenInt会发生什么,那就不能够在所有的改变结构,只是它所包含的内容。你会更好写一个函数像

smap :: (Ord a, Ord b) => (a -> b) -> S a -> S b 
smap f = fromList . map f . toList 

或者,也许一个更有效的,但仍然有可能改变结构本身,而不仅仅是价值的能力。

这不完全是一个限制,它是Functor法律必须满足,以便fmap正常行为。这似乎不是什么大不了的事情,但请查看各种各样ListT实现的有争议的历史,以及它们如何不都满足monad法则。