haskell - 了解如何应用 haskell 应用函子
问题描述
我只是有一个关于应用函子的快速问题,以帮助我掌握它们。这只是我在 ghci 中应用的东西。
[(+3),((-) 3),(*3)] <*> [4]
[7,-1,12]
这对我来说很有意义。基础应用。但是在尝试时:
[(Just (+3)),(Just ((-) 3)),(Just (*3))] <*> [Just 4]
我得到了大量的错误。我有点理解为什么;有两个数据构造函数 ( []
and Maybe
),并且该<*>
函数仅“剥离”其中一个。我想帮助我理解的是,haskell 到底在尝试一步一步做些什么,直到它失败,以及如何绕过它并成功计算到:
[(Just 7),(Just -1),(Just 12)]
解决方案
您有两个不同的Applicative
实例。的确如此
Just (* 3) <*> Just 4 == Just 12
但是该[]
实例只是尝试将第一个列表中的每个“函数”应用于第二个列表中的每个值,因此您最终尝试应用
(Just (* 3)) (Just 4)
这是一个错误。
(更准确地说,您的Just
值列表只是具有错误的类型来充当 的第一个参数<*>
。)
相反,您需要映射<*>
第一个列表。
> (<*>) <$> [(Just (+3)),(Just ((-) 3)),(Just (*3))] <*> [Just 4]
[Just 7,Just (-1),Just 12]
(在列表上映射高阶函数通常是首先获得包装函数列表的方式。例如,
> :t [(+3), ((-) 3), (* 3)]
[(+3), ((-) 3), (* 3)] :: Num a => [a -> a]
> :t Just <$> [(+3), ((-) 3), (* 3)]
Just <$> [(+3), ((-) 3), (* 3)] :: Num a => [Maybe (a -> a)]
)
Data.Functor.Compose
评论中提到的是另一种选择。
> import Data.Functor.Compose
> :t Compose [(Just (+3)),(Just ((-) 3)),(Just (*3))]
Compose [(Just (+3)),(Just ((-) 3)),(Just (*3))]
:: Num a => Compose [] Maybe (a -> a)
> Compose [(Just (+3)),(Just ((-) 3)),(Just (*3))] <*> Compose [Just 4]
Compose [Just 12,Just (-1),Just 12]
> getCompose <$> Compose [(Just (+3)),(Just ((-) 3)),(Just (*3))] <*> Compose [Just 4]
[Just 12,Just (-1),Just 12]
的定义Compose
很简单:
newtype Compose f g a = Compose { getCompose: f (g a) }
神奇的是,只要f
和g
都是(应用)函子,那么Compose f g
也是(应用)函子。
instance (Functor f, Functor g) => Functor (Compose f g) where
fmap f (Compose x) = Compose (fmap (fmap f) x)
instance (Applicative f, Applicative g) => Applicative (Compose f g) where
pure x = Compose (pure (pure x))
Compose f <*> Compose x = Compose ((<*>) <$> f <*> x)
在该Applicative
实例中,您可以看到(<*>) <$> ...
我上面使用的相同用法。
推荐阅读
- android - Ionic Android 应用程序未收到 Phonegap 推送通知
- http-live-streaming - 创建循环相同片段的无限 HLS 流时如何使用 EXT-X-DISCONTINUITY-SEQUENCE
- r - 如何在 Shiny 中提取动态生成的输入值?
- android - 从着色器获取纹理坐标到 CPU 端
- ibm-bpm - ibm bpm - 执行 sql 语句返回类型
- reactjs - React - 在 div 中映射内容
- python - 如何避免在基本模板中呈现块 - 或者:如何定义多行块状变量?
- java - 在java中将自动值导出到excel文件
- c# - 在 Windows Iot 的外部驱动器上创建、写入、读取 SQLite DB
- swift - Swift - 使用泛型实现存储库模式