haskell - 关于应用程序的多个参数不起作用?
问题描述
所以我正在尝试学习单子、函子和应用程序。我创建了以下名为的重命名镜像Maybe
匹配Sometimes
。(我这样做是为了了解这些事情)
data Sometimes a = Nope | Thing a deriving Show
instance Monad Sometimes where
(Thing x) >>= f = f x
Nope >>= f = Nope
return = Thing
instance Applicative Sometimes where
pure = Thing
Nope <*> _ = Nope
(Thing g) <*> mx = fmap g mx
instance Functor Sometimes where
fmap _ Nope = Nope
fmap g (Thing x) = Thing (g x)
因此,当我执行以下操作时,它会起作用:
pure (1+) <*> (Thing 1)
> Thing 2
pure (+) <*> (Thing 1) <*> (Thing 1)
> Thing 2
但是如果我尝试三个添加它不起作用:
pure (+) <*> (Thing 1) <*> (pure 1) <*> (pure 1)
<interactive>:108:1: error:
• Non type-variable argument in the constraint: Num (a -> b)
(Use FlexibleContexts to permit this)
• When checking the inferred type
it :: forall a b. (Num (a -> b), Num a) => Sometimes b
为什么这不起作用?我希望前两个被应用,然后第三个被应用到前两个的结果。我的书谈到了实施fmap0, fmap1, fmap2...
是如何低效的,因此
... 对于具有任意数量参数的函数,可以根据具有以下类型的两个基本函数来构造:
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
并进一步说明:
pure
和的典型用法<*>
有以下形式:pure g <*> x1 <*> x2 <*> ... <*> xn
因此,我希望它能够工作,但我显然在我的定义/使用中遗漏了一些东西Applicative
。
我正在使用 Graham Hutton 所著的《Haskell SE 编程》一书
解决方案
这不起作用的原因是因为(+)
两个数字相加,而不是三个。
您可以创建一个对三个数字求和的函数,例如:
pure (\x y z -> x+y+z) <*> (Thing 1) <*> (pure 1) <*> (pure 1)
这给了我们:
Prelude> pure (\x y z -> x+y+z) <*> (Thing 1) <*> (pure 1) <*> (pure 1)
Thing 3
为什么这不起作用?我希望前两个被应用,然后第三个被应用到前两个的结果。
没错,但是在应用了前两个之后,这不再是一个函数,而是一个Num a => Sometimes a
. 事实上,如果我们确定类型,我们会看到Thing (+) :: Num a => Sometimes (a -> a -> a)
and Thing 1 :: Num b => Sometimes b
,所以这意味着它Thing (+) <*> Thing 1
有 type Num a => Sometimes (a -> a)
。
然后我们确定 的类型Thing (+) <*> Thing 1 <*> Thing 1
,因为Thing (+) <*> Thing 1
有类型Num a => Sometimes (a -> a)
,最后Thing 1
有类型Num c => Sometimes c
,这意味着Thing (+) <*> Thing 1 <*> Thing 1
有类型Num a => Sometimes a
,但这不是函数,除非有一个Num
类型是函数,这就是错误的意思。
推荐阅读
- environment-variables - 卸载程序路径,而不是整个系统“路径”
- asp.net - 删除请求失败,出现 415 Unsupported Media Type
- jquery - 进度条上的返回按钮
- java - Selenium 处理 for 循环中的陈旧元素
- event-handling - 如何根据 Julia 中的事件实现 ODE 解决方案的终止?为什么我会收到 BoundsError?
- c# - _base_ 值上的空对象模式
- vue.js - 使用 Vue Observable 在同一视图上使用 v-dialog 组件两次出现“超出最大调用堆栈大小”错误
- npm - npm 安装不能使用 squid 代理
- c - 宏中的## 运算符如何工作?
- laravel-5.7 - 查询生成器中的 where 条件中的 where 子句,表示未定义的变量