haskell - 如何为具有两个参数的类型实例化 `Functor`?
问题描述
背景。在我的一堂课上,我们一直在探索Parser
单子。Parser
monad 通常被定义为
newtype Parser a = Parser (String -> [(a, String)])
或者作为
newtype Parser a = Parser (String -> Maybe (a, String))
在任何一种情况下,我们都可以Parser
作为Functor
在这两种情况下都有效的使用代码进行实例化:
instance Functor Parser where
fmap f (Parser p) = Parser (fmap applyF . p)
where applyF (result, s) = (f result, s)
如果我们有一个Parser
build to return Maybe (a, String)
,这适用f
于result
if the result
exists。如果我们有一个Parser
内置的 return [(a, String)]
,这适用于列表中返回的f
每个result
s。
我们可以实例化Applicative
, Monad
, MonadPlus
, 和Alternative
类似的通用方式(以便它们适用于Maybe
或[]
)。
问题。如果我Parser
根据用于包装结果的类型进行参数化,我如何为Functor
和朋友实例化它?
newtype Parser m a = Parser (String -> m (a, String))
-- How do I instance `Parser` as a Functor if `m` is a Functor?
解决方案
您可以在此处构造一个约束,该约束m
应该是一个实例的类型,Functor
然后fmap
在该结果上:
instance Functor m => Functor (Parser m) where
fmap f (Parser p) = Parser (\x -> fmap g (p x))
where g (r, s) = (f r, s)
因此,这是一个对元组的第一个元素g
执行映射的函数。f
因此,我们将其g
用作结果的“映射”函数。
因此,这将适用于任何m
实例Functor
,例如 a Maybe
、 a []
、 aTree
等。
推荐阅读
- mongodb - 使用 pymongo 获取集合模式
- node.js - 如何根据下拉列表中选择的值添加新的 div
- reactjs - 如何为 react-calendar 创建事件
- angular - Angular 2+ @ng-select/ng-select:如何更改键、值数组
- anylogic - 在 RunTime 之前编辑参数
- c# - 替换自定义键盘键以出现在 C# 的 RichTextbox 中
- c++ - 如何使用犰狳 c++ 库计算 Excel Percentile.exc?
- file - 读取大于 500 MB 的文件时 Luajit “内存不足”
- windows-10 - 在 Windows 10 中更改用户名后如何收回配置文件文件夹的权限?
- visual-studio-code - VSCode 如何找回菜单?