首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >违禁品的目的是什么?

违禁品的目的是什么?
EN

Stack Overflow用户
提问于 2018-02-02 16:52:33
回答 2查看 2.4K关注 0票数 3

我读了很多关于违禁品的文章,发现https://hackage.haskell.org/package/contravariant-1.4.1/docs/Data-Functor-Contravariant.html#g:3是最好的。

无论如何,我发现,如何使用例如:

代码语言:javascript
复制
*Lib Data.Functor.Contravariant> a = Predicate (\x -> x > 20)
*Lib Data.Functor.Contravariant> :t contramap
contramap :: Contravariant f => (a -> b) -> f b -> f a
*Lib Data.Functor.Contravariant> :t contramap (\x -> x * 2)
contramap (\x -> x * 2) :: (Num b, Contravariant f) => f b -> f b
*Lib Data.Functor.Contravariant> :t contramap (\x -> x * 2) a
contramap (\x -> x * 2) a :: (Ord b, Num b) => Predicate b
*Lib Data.Functor.Contravariant> x = contramap (\x -> x * 2) a
*Lib Data.Functor.Contravariant> getPredicate x 45
True 

但却找不出,哪里可以有用。

在我上面发布的网站上,上面写着:

在Haskell中,人们可以认为函子包含或产生值,相反的函子是可以被认为是消费价值的函子。

请看函子的定义:

代码语言:javascript
复制
class Functor (f :: * -> *) where
  fmap :: (a -> b) -> f a -> f b

它使用a类型的值,并生成b类型的值。在contramap上,它消耗了这个值。

代码语言:javascript
复制
class Contravariant (f :: * -> *) where
  contramap :: (a -> b) -> f b -> f a

它使用哪种变量类型的ab

https://www.fpcomplete.com/blog/2016/11/covariance-contravariance也有一个关于正负位置的问题。网站上写着:

  • 正位置:类型变量是函数的结果/输出/范围/余域。
  • 负位置:类型变量是函数的参数/输入/域。

查看违禁品类型定义:

代码语言:javascript
复制
contramap :: (a -> b) -> f b -> f a

作者指向哪个类型的变量?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-02-02 17:15:31

函子f被认为是“包含”或“生成”值,因为f a就像a值的容器。fmap允许您转换f所持有的值。

示例:

  • [a]‘包含一个非负数的a类型值。
  • IO a可能会执行一些IO和“返回”或“生成”a类型的值。
  • (->) r a‘包含一个a类型的值,用于r的每个值

现在,Contravariant f是一种可以“接受”或“消费”价值的东西。contramap允许您转换f a在消耗它们之前获取的东西。

这方面的主要示例通常是使用以下内容

newtype Op r a = Op { runOp :: a -> r }

(请注意,您使用的Predicate似乎只是Op Bool)

现在,我们有了一些可以“消费”a类型值的东西。(这个类比对于Op (IO ())来说可能更有意义)

继续这个“消耗”值的例子,考虑o = Op (\x -> putStrLn x) :: Op (IO ()) String,现在如果我们想要使用o,但是对于Show a => a类型的值呢?这就是contramap的目的!

contramap show o :: Show a => Op (IO ()) a

(注意,在这个简单的例子中,runOp (contramap show o)只是print)

编辑:

关于Contravariant的另一件有趣的事情是关于它的组成。

给定Contravariant c, Contravariant d, Functor f

newtype Compose f g a = Compose { runCompose :: f (g a) }

我们有:

  • Compose f c也是Contravariant contramap f (Compose fca) = Compose $ fmap (contramap f) fca
  • Compose c f也是Contravariant contramap f (Compose cfa) = Compose $ contramap (fmap f) cfa
  • Compose c d实际上是一个Functor fmap f (Compose cda) = Compose $ contramap (contramap f) cda
票数 9
EN

Stack Overflow用户

发布于 2022-07-05 17:52:47

首先,看看签名,一切都在那里。

第二,如果你想“感觉”这些事情,考虑一下函子,试着用语言表达他们所做的事情。

函子用其包含的类型做某事。这可以是一种消费,也可以是这类产品的生产。一个列表,清楚地“生成”类型的实例。显然,打印机“消耗”类型的实例。

当给定一个函数时,生产者构建一个函数来转换生产“后”。从一个简单的函数中,您可以在生产之后应用函数域获得一个生产者。fmap的签名是“协变”的。

当给定一个函数时,消费者会构建一个函数来转换“以前”的消费。通过提供从int到string的转换器函数,已经持有字符串使用者的使用者将很容易地生成int的使用者:在消费前应用该函数。违禁品的签名是“反变体”。

我们可以说,功能“转换”,而函子“消费”或“生产”。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48587361

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档