haskell - 以下类型的 Functor 实例是什么: newtype F2 xa = F2 ((a -> x) -> a)
问题描述
所以我想为上述类型编写 fmap 函数,但我被困在这里:
instance Functor (F2 x) where
fmap :: (a -> b) -> (F2 x a) -> (F2 x b)
fmap f (F2 g) = F2 ( f _ )
解决方案
这里一个好的策略是遵循类型。如果我们用类型空洞编写不完整的定义,GHC 可以帮助我们:
newtype F2 x a = F2 ((a -> x) -> a)
instance Functor (F2 x) where
fmap f (F2 g) = _
如果我们尝试编译它,GHC 会报告:
Diatonic.hs:275:21: error:
• Found hole: _ :: F2 x b
Where: ‘b’ is a rigid type variable bound by
the type signature for:
fmap :: forall a b. (a -> b) -> F2 x a -> F2 x b
at Diatonic.hs:275:5-8
‘x’ is a rigid type variable bound by
the instance declaration
at Diatonic.hs:274:10-23
• In the expression: _
In an equation for ‘fmap’: fmap f (F2 g) = _
In the instance declaration for ‘Functor (F2 x)’
• Relevant bindings include
g :: (a -> x) -> a (bound at Diatonic.hs:275:16)
f :: a -> b (bound at Diatonic.hs:275:10)
fmap :: (a -> b) -> F2 x a -> F2 x b (bound at Diatonic.hs:275:5)
|
275 | fmap f (F2 g) = _
|
这意味着我们必须用一个F2 x b
值来填充这个洞。我们创建一个的唯一方法是使用构造函数(对于以下步骤,我将省略不变的样板):
fmap f (F2 g) = F2 _
• Found hole: _ :: (b -> x) -> b
所以我们需要一个接受b -> x
. 我们可以设置一个。让我们调用它的参数k
,看看我们是否可以完成它的主体:
fmap f (F2 g) = F2 (\k -> _)
• Found hole: _ :: b
唯一可以产生 a 的b
是f :: a -> b
:
fmap f (F2 g) = F2 (\k -> f _)
• Found hole: _ :: a
唯一可以产生 an 的a
是g :: (a -> x) -> a
:
fmap f (F2 g) = F2 (\k -> f (g _))
• Found hole: _ :: a -> x
我们应该提供一个a -> x
函数,所以让我们引入另一个 lambda(可能的捷径,请参阅答案的最后部分):
fmap f (F2 g) = F2 (\k -> f (g (\a -> _)))
• Found hole: _ :: x
唯一能产生a的x
是k :: b -> x
fmap f (F2 g) = F2 (\k -> f (g (\a -> k _)))
• Found hole: _ :: b
唯一可以产生b
静止图像的是f :: a -> b
:
fmap f (F2 g) = F2 (\k -> f (g (\a -> k (f _))))
• Found hole: _ :: a
如果我们像前几步那样尝试用它g
来创造a
价值,我们就会陷入恶性循环。但是,这次我们不必这样做,因为a
lambda 的参数在范围内:
fmap f (F2 g) = F2 (\k -> f (g (\a -> k (f a))))
我们完成了。
(值得一提的是,你F2
是由transformers提供的,它被称为Select
。)
\a -> k (f a)
如果我们写pointfree ,定义可以说看起来更整洁:
instance Functor (F2 x) where
fmap f (F2 g) = F2 (\k -> f (g (k . f)))
通过注意到我们a -> x
唯一可行的选择是 composef :: a -> b
和k :: b -> x
.
推荐阅读
- azure - 如何使用 LUIS 和 Azure Bot 服务从 SQL Server 获取数据
- javascript - 如何用Three.JS制作曲线图片动画
- python - 聚焦打印张量的实际行和列(不是“,”形状)
- json - 如何在 PouchDB 中存储具有循环的图形?
- java - 有没有办法根据值列表(来自@configurationproperties)验证@RequestHeader
- email - Microsoft Graph API:尝试获取 Outlook 邮箱的消息,但改为获取“ResourceNotFound”
- sqlite - 如何使用 sqlite-net-pcl 和 sqliteExtensions 从 xamarin 表单中的外键表中添加/加载/删除项目
- docker - docker : 不要覆盖基础镜像入口点
- python-3.x - pytest 为所有测试存根方法
- python - Python - 正确的包管理导致代码问题?曾经工作的代码现在出错了