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
,那么你可以通过首先将它们转换为 Integer
s 并测试它们来测试 String
s,这样你就可以得到 从Set Integer
到Set String
。但是 g :: Integer -> String
并不能让你测试 Strings
!
如果这是一个赋值,那么要么你误解了赋值,要么你之前的一些步骤与预期的不同(例如,如果你在前面的部分自己定义了 Set
,也许你需要更改定义),或者您的讲师可能希望您能解决这个问题并理解为什么 Functor
无法定义。
我正在为 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
,那么你可以通过首先将它们转换为 Integer
s 并测试它们来测试 String
s,这样你就可以得到 从Set Integer
到Set String
。但是 g :: Integer -> String
并不能让你测试 Strings
!
如果这是一个赋值,那么要么你误解了赋值,要么你之前的一些步骤与预期的不同(例如,如果你在前面的部分自己定义了 Set
,也许你需要更改定义),或者您的讲师可能希望您能解决这个问题并理解为什么 Functor
无法定义。