英文:
What's the meaning of `fmap` over set of predicates in Haskell?
问题
Here's the translated code portion:
我正在进行的Haskell编程的学生作业包括一个我有点困惑的任务。事情是这样的:需要为一个基于集合的新类型创建Functor类的实例。声明如下:
newtype Set x = Set { contains :: (x -> Bool) }
对于我来说,理解`fmap`如果用于类似谓词集合的东西意味着什么是个难题。在处理之前的任务时,我已经定义了`fmap`,通常是与诸如`(+3)`(用于更改整数)、`toUpper`(用于字符串)等函数一起使用的。这是我第一次处理超出正常类型(各种数字、String、Char)的内容。这是我谦虚的尝试:
instance Functor Set where
fmap f (Set x) = if (contains x) == True then Set (f x) else Set x
当然,这是一段无意义的代码,但我认为在`fmap`应用之前需要评估一些True/False。首先,您能否解释一下谓词集合的问题,以便更详细地说明更明智的方法?
英文:
My student assignment I'm doing for Haskell programming includes a task I'm a little bit puzzled to solve. The things are given so: an instance of Functor class to be created just for a set-based new type. There is a declaration of that:
newtype Set x = Set { contains :: (x -> Bool) }
It's a case for me to understand what means if fmap
serves to be applied to something like a set of predicates. When doing about previous tasks, I've already defined fmap
rather with functions like (+3)
(to alter integers), (toUpper)
(to strings) etc. It's first time I'm dealing with anything beyond normal types (various numerics, String, Char). There is my humble attempt to start:
instance Functor Set where
fmap f (Set x) = if (contains x) == True then Set (f x) else Set x
Surely, it's a nonsense code, but I suppose some True/False need to be evaluated before fmap
apllication goes well. But, first of all, would you please explain the matter of set of predicates to elaborate more sensible approach?
答案1
得分: 9
根据这个定义,实际上不可能为Set
定义一个Functor
实例。原因是你的Set a
类型在负面位置包含了a
...也就是说,a
是一个函数的参数,而不是一个值。当发生这种情况时,类型构造器可以是一个反变协变子(来自contravariant
包的Contravariant
类型类),但不能是协变子(Functor
类型类)。
以下是这些类的定义:
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Contravariant f where
contramap :: (a -> b) -> f b -> f a
看到区别了吗?在反变协变子中,传入的函数的方向在提升到协变子类型时被翻转。
最终,这应该能够理解。你对“集合”的概念是一个告诉你某物是否符合条件的测试。这是一个完全合理的数学定义,但它赋予你不同的计算能力,与标准定义不同。例如,你无法访问基于谓词的集合的元素;只能等待被提供一个潜在元素。如果你有一个Set Integer
,以及一个函数f :: String -> Integer
,那么你可以通过首先将它们转换为Integer
并测试它们来测试String
,因此你可以从Set Integer
获得到Set String
。但是拥有一个g :: Integer -> String
却不允许你测试String
!
如果这是一个作业,那么要么你误解了作业,要么你在早期步骤中做了与预期不同的事情(例如,如果你在早期部分自己定义了Set
,也许你需要更改定义),或者你的教练希望你在这方面有所挣扎,并理解为什么无法定义Functor
。
英文:
With this definition, it is actually impossible to define a Functor
instance for Set
. The reason for this is that your Set a
type contains a
in a negative position... that is, a
is an argument to a function, not a value. When that happens, the type constructor can be a contravariant functor (type class Contravariant
from the contravariant
package), but it cannot be a covariant functor (the Functor
type class).
Here's are definitions of those classes:
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Contravariant f where
contramap :: (a -> b) -> f b -> f a
See the difference? In a contravariant functor, the direction of the function you pass in is flipped when it's lifted to operate on the functor type.
In the end, this should make sense. Your notion of a "set" is a test that tells you whether something qualifies or not. This is a perfectly good mathematical definition of a set, but it gives you different computational powers than the standard one. For example, you cannot get at the elements of your predicate-based sets; only wait to be given a potential element. If you have a Set Integer
, and a function f :: String -> Integer
, then you can test String
s by first converting them to Integer
s and testing those, so you can get from Set Integer
to Set String
. But having a g :: Integer -> String
doesn't let you test Strings
!
If this is an assignment, then either you've misunderstood the assignment, you've done some earlier step differently than expected (e.g., if you defined Set
yourself in an earlier part, maybe you need to change the definition), or perhaps your instructor is hoping you'll struggle with this and understand why Functor
cannot be defined.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论