这个问题可能看起来有点傻,但我会先问出来,然后解释一下背后的原理。
假设我们按照以下方式重新定义Functor
:
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
class Functor a where
generic_fmap :: a
instance Functor ((a -> b) -> Maybe a -> Maybe b) where
generic_fmap f (Just x) = Just (f x)
generic_fmap _ Nothing = Nothing
instance Functor ((a -> b) -> [a] -> [b]) where
generic_fmap = map
-- etc with more instances
然后,我考虑了两种定义
fmap
的方法。(1):
fmap :: (Functor ((a -> b) -> f a -> f b)) => (a -> b) -> f a -> f b
fmap = generic_fmap
或者(2)需要不可判定实例的情况下(已编辑):
class Functor f a b where
fmap :: (a -> b) -> f a -> f b
instance (GenericFunctor ((a -> b) -> f a -> f b)) => Functor f a b where
fmap = generic_fmap
除了打字速度变慢和不美观之外,我们在这两种方式中定义fmap时还会失去什么吗?
我问这个问题的原因是,我发现标准的Functor类比数学定义更加具体,因此许多本应符合Functor的事物在Haskell中却不能作为Functor。我的想法是定义一个非常通用的Functor类(也许并不像上面那么通用)。但是,如果它太通用,您会失去类型推断。因此,用户可以根据需要选择使用不同版本的fmap,就像用户可以在prelude中选择.(仅适用于标准函数)或者在Control.Category中选择.(适用于所有范畴)一样。
我知道还有许多向后兼容性问题,但我的第一个问题是,我的定义是否与实例中的用户(暂不考虑那些想要定义实例的人)相同。
Functor
添加了a
和b
参数。这使得它成为一个非常不同的问题:现在可以使用GHC进行定义(我的原始答案不再适用于此版本)。然而,与此同时,你的问题的答案现在是明确的否定:现在有许多用例无法正常工作,即任何你不想提前固定a
和b
的情况。即使它仍然有效,所有类型签名也需要更改。 - Ørjan JohansenFunctor
类的泛化([1] [2] [3]),都不够通用吗? - leftaroundabout