约束实例方法
Constrain an instance method
我要写:
{-# 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 一直在打击我
Method signature does not match class
问题:
- 你知道解决方法吗?
- 这个限制解决了什么问题?
你不能,简单地说。 Functor
class 被定义为它必须与所有 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
这只会将 even
应用到集合中的每个 Int
,它根本无法改变结构,只能改变它包含的内容。你最好写一个像
这样的函数
smap :: (Ord a, Ord b) => (a -> b) -> S a -> S b
smap f = fromList . map f . toList
或者可能更高效,但仍然能够更改结构本身,而不仅仅是值。
这并不是严格意义上的限制,而是必须满足 Functor
法则才能使 fmap
正常运行。这可能看起来没什么大不了的,但是去看看各种 ListT
实现的有争议的历史,以及它们如何不都满足 monad 法则。
我要写:
{-# 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 一直在打击我
Method signature does not match class
问题:
- 你知道解决方法吗?
- 这个限制解决了什么问题?
你不能,简单地说。 Functor
class 被定义为它必须与所有 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
这只会将 even
应用到集合中的每个 Int
,它根本无法改变结构,只能改变它包含的内容。你最好写一个像
smap :: (Ord a, Ord b) => (a -> b) -> S a -> S b
smap f = fromList . map f . toList
或者可能更高效,但仍然能够更改结构本身,而不仅仅是值。
这并不是严格意义上的限制,而是必须满足 Functor
法则才能使 fmap
正常运行。这可能看起来没什么大不了的,但是去看看各种 ListT
实现的有争议的历史,以及它们如何不都满足 monad 法则。