[英]Why can't I use 'isJust' in the lambda function in `foldr`?
I am currently writing an interpreter in haskell for a primitive programming language.我目前正在 haskell 中为原始编程语言编写解释器。 I am trying to see if the current program being analysed is correctly Typed before interpreting.
我试图在解释之前查看当前正在分析的程序是否正确键入。 Basically what I end up with is a list called
maybeList
that holds maps of the initialised variables if they are correct, or Nothing
s if they don't, like this:基本上我最终得到的是一个名为
maybeList
的列表,如果它们是正确的,它会保存初始化变量的映射,或者如果它们不正确,则保存Nothing
,如下所示:
[Maybe [(k,v)]]
I am trying to fold over this list with this function我试图用这个 function 折叠这个列表
foldr (\xy -> (isJust x) && (isJust y)) True maybeList
From what I understand about Haskell and the foldr
function, this should work.根据我对 Haskell 和文件夹
foldr
的了解,这应该可以工作。 However, it gives me the error:但是,它给了我错误:
Couldn't match expected type 'Bool' with actual type 'Maybe a0' In the expression: foldr (\ xy -> (isJust x) && (isJust y)) True maybeList
What I'm asking is why doesn't the compiler know that the isJust
function returns a boolean, it keeps treating it as a Maybe a0
type?我要问的是为什么编译器不知道
isJust
function 返回 boolean,它一直将其视为Maybe a0
类型?
PS I understand that a simple elem Nothing maybeList
will work in place of this. PS 我知道一个简单的
elem Nothing maybeList
可以代替它。 But I would like to understand why this doesn't work但我想了解为什么这不起作用
The reducing function for foldr
takes as second argument something of the same type as the initial element: foldr
的减少function 将与初始元素类型相同的东西作为第二个参数:
foldr (\x y -> (isJust x) && (isJust y)) True maybeList
-- \_______________________________/
-- |
-- these two must be the same type
So y
is of type Bool
but you are considering it of type Maybe a
.所以
y
是Bool
类型,但您正在考虑它是Maybe a
类型。
Therefore, foldr (\xy -> (isJust x) && y) True maybeList
is the right solution.因此,
foldr (\xy -> (isJust x) && y) True maybeList
是正确的解决方案。
A foldr
takes as second parameter the accumulator . foldr
将accumulator作为第二个参数。 Indeed, the type of foldr
is:实际上,
foldr
的类型是:
foldr :: Foldable f => (a ->
b ->
b) ->
b -> f a ->
b
Here b
is the type of the accumulator that goes conceptually from right-to-left, whereas a
are the items of the list.这里
b
是从概念上从右到左的累加器的类型,而a
是列表的项目。
Since you work with True
in foldr (\xy -> isJust x && isJust y)
, this thus means that the accumulator, and hence True
y
also is of type Bool
.由于您在
foldr (\xy -> isJust x && isJust y) True
中使用True
,因此这意味着累加器,因此y
也是Bool
类型。
We can implement this with:我们可以通过以下方式实现:
foldr (\x y -> isJust x &&
y) True maybeList
We however do not need foldr
here.然而,我们在这里不需要
foldr
。 What you here determine is whether all the items are a Just …
.您在这里确定的是所有项目是否都是
Just …
。 We can thus work with all:: Foldable f => (a -> Bool) -> fa -> Bool
:因此,我们可以使用
all:: Foldable f => (a -> Bool) -> fa -> Bool
:
all isJust maybeList
The problem is in the part isJust y
, y
is the result of the fold for the tail of the list and therefore has type Bool
.问题在于
isJust y
部分, y
是列表尾部折叠的结果,因此具有Bool
类型。 Just like the second argument True
you are giving to the foldr
function.就像第二个参数
True
一样,您将给foldr
function。
You can't call isJust
on a value of type Bool
.您不能在
Bool
类型的值上调用isJust
。 A simple fix would be to leave out the isJust
.一个简单的解决方法是
isJust
。
The full error messages I get are:我收到的完整错误消息是:
<interactive>:3:16: error:
• Couldn't match expected type ‘Maybe a’ with actual type ‘Bool’
• In the expression: (isJust x) && (isJust y)
In the first argument of ‘foldr’, namely
‘(\ x y -> (isJust x) && (isJust y))’
In the expression:
foldr (\ x y -> (isJust x) && (isJust y)) True maybeList
• Relevant bindings include
y :: Maybe a (bound at <interactive>:3:11)
it :: Maybe a (bound at <interactive>:3:1)
<interactive>:3:42: error:
• Couldn't match expected type ‘Maybe a’ with actual type ‘Bool’
• In the second argument of ‘foldr’, namely ‘True’
In the expression:
foldr (\ x y -> (isJust x) && (isJust y)) True maybeList
In an equation for ‘it’:
it = foldr (\ x y -> (isJust x) && (isJust y)) True maybeList
• Relevant bindings include
it :: Maybe a (bound at <interactive>:3:1)
Which shows that GHC interprets it the wrong way around.这表明 GHC 以错误的方式解释它。 It thinks that you meant to have the result be of type
Maybe a0
for some a0
.它认为你的意思是让一些
a0
的结果是Maybe a0
类型。 Then the second argument of foldr
, namely True
, has the wrong type and the result of the lambda has the wrong type.然后
foldr
的第二个参数True
类型错误, lambda 的结果类型错误。
The type of foldr
is foldr
的类型是
foldr :: (a -> b -> b) -> b -> t a -> b
which means your lamda expression should take a Bool
for it's second argument, whereas in your case it expects a Maybe
.这意味着您的 lamda 表达式应该将
Bool
作为第二个参数,而在您的情况下,它需要一个Maybe
。
@Ismor has the correct explanation. @Ismor 有正确的解释。
Note that Haskell has a library function*注意 Haskell 有一个库函数*
all :: (a -> Bool) -> [a] -> Bool
all f = foldr (\x y -> f x && y) True
So the solution of foldr (\xy -> isJust x && y) True maybeList
is equivalent to all isJust maybeList
.所以
foldr (\xy -> isJust x && y) True maybeList
的解等价于all isJust maybeList
。
Thus, the solution reads exactly like the specification: check to see if all elements of maybeList
are Just
=> all isJust maybeList
.因此,该解决方案与规范完全一样:检查
maybeList
的所有元素是否为Just
=> all isJust maybeList
。
* Technically, the type of all
is * 从技术上讲,
all
的类型是
all :: (Foldable f) => (a -> Bool) -> f a -> Bool
So any type constructor which implements the Foldable
typeclass can be checked to see whether all its elements satisfy a particular predicate.因此,可以检查实现
Foldable
类型类的任何类型构造函数,以查看其所有元素是否满足特定谓词。 You can thus use this for trees, lists, Maybes, etc.因此,您可以将其用于树、列表、Maybes 等。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.