简体   繁体   English

为什么我不能在“foldr”中的 lambda function 中使用“isJust”?

[英]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 .所以yBool类型,但您正在考虑它是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 . foldraccumulator作为第二个参数。 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) True , this thus means that the accumulator, and hence 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM