Haskell 中谓词集上的 `fmap` 是什么意思?

What's the meaning of `fmap` over set of predicates in Haskell?

我正在为 Haskell 编程做的学生作业包括一个我有点困惑的任务。事情是这样给出的:一个 Functor class 的实例只是为了一个基于集合的新类型而创建的。有一个声明:

newtype Set x = Set { contains :: (x -> Bool) }

如果 fmap 应用于一组谓词之类的东西,我会理解这意味着什么。在处理之前的任务时,我已经定义了 fmap 而不是 (+3)(更改整数)、(toUpper)(更改字符串)等函数。这是我第一次处理超出正常类型的任何内容(各种数字、字符串、字符)。这是我开始的卑微尝试:

instance Functor Set where
    fmap f (Set x) = if (contains x) == True then Set (f x) else Set x

当然,这是一个无意义的代码,但我想在 fmap 应用顺利之前需要评估一些 True/False。但是,首先,请您解释一下谓​​词集的问题以详细说明更明智的方法吗?

用这个定义,实际上不可能为Set定义一个Functor实例。这样做的原因是你的 Set a 类型在 negative 位置包含 a...也就是说,a 是函数的参数,不是一个值。当发生这种情况时,类型构造函数可以是逆变函子(类型 class Contravariant 来自 contravariant 包),但它不能是协变函子(Functor 类型 class).

下面是那些 classes 的定义:

class Functor f where
    fmap :: (a -> b) -> f a -> f b

class Contravariant f where
    contramap :: (a -> b) -> f b -> f a

看出区别了吗?在逆变函子中,您传入的函数的方向在提升以对函子类型进行操作时翻转。

最后,这应该是有道理的。您的 "set" 概念是一个测试,告诉您某事是否合格。这是集合的一个非常好的数学定义,但它为您提供了与标准集合不同的计算能力。例如,您无法获取基于谓词的集合的元素;只能等待被赋予一个潜在的元素。如果你有一个 Set Integer 和一个函数 f :: String -> Integer,那么你可以通过首先将它们转换为 Integers 并测试它们来测试 Strings,这样你就可以得到 Set IntegerSet String。但是 g :: Integer -> String 并不能让你测试 Strings!

如果这是一个赋值,那么要么你误解了赋值,要么你之前的一些步骤与预期的不同(例如,如果你在前面的部分自己定义了 Set,也许你需要更改定义),或者您的讲师可能希望您能解决这个问题并理解为什么 Functor 无法定义。