为什么模式匹配失败时,Haskell列表解析会导致错误? [英] Why don't Haskell list comprehensions cause an error when pattern match fails?

查看:113
本文介绍了为什么模式匹配失败时,Haskell列表解析会导致错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图理解Haskell列表解析如何在模式匹配方面引擎盖下工作。下面的ghci输出说明了我的观点:

  Prelude> let myList = [只有1,只有2,没有,只有3] 
Prelude>让xs = [x | Just x< - myList]
Prelude> xs
[1,2,3]
前奏>

正如您所看到的,它可以跳过Nothing并只选择Just值。我知道List是一个monad,定义为(来自Real World Haskell,第14章):

pre $实例Monad []
return x = [x]
xs>> = f = concat(map f xs)
xs>> f = concat(map(\_> f)xs)
fail _ = []


$ b $因此,列表理解基本上为在列表理解中选择的每个元素建立一个单独列表并将它们连接起来。如果模式匹配在某个步骤失败,则使用失败功能的结果。换句话说,Just x模式不匹配,所以[]用作占位符,直到调用'concat'。这就解释了为什么Nothing似乎被忽略。



我不明白的是,Haskell如何知道调用失败函数?它是编译器魔术还是可以在Haskell中编写的功能?是否可以编写下面的select函数以与列表理解相同的方式工作?

  select ::(a - > b) - > [a]  - > [b] 
select(Just x - > x)myList - 如何防止lambda引发错误?
[1,2,3]


解决方案

虽然Haskell的实现可能不会像内部那样直接执行,但这样考虑它会很有帮助:)

  [x |只需x < -  myList] 

...变成:

  do 
只需x < - myList
返回x

...这是:

  myList>> = \(只要x) - >返回x 

至于您的问题:


我不明白的是,Haskell是如何知道调用fail函数的?

在注解中,如果模式绑定失败(即 Just x ),则调用fail方法。对于上面的例子,它看起来像这样:

  myList>> = \temp  - >案例温度
(Just x) - >返回x
_ - >失败...

因此,每次在单一语境中进行模式匹配时可能会失败,Haskell会插入对失败的调用。用IO来试用它:

  main = do 
(1,x)< - return(0,2 )
print x - x将为2,但模式匹配失败


I'm trying to understand how Haskell list comprehensions work "under the hood" in regards to pattern matching. The following ghci output illustrates my point:

Prelude> let myList = [Just 1, Just 2, Nothing, Just 3]
Prelude> let xs = [x | Just x <- myList]
Prelude> xs
[1,2,3]
Prelude>

As you can see, it is able to skip the "Nothing" and select only the "Just" values. I understand that List is a monad, defined as (source from Real World Haskell, ch. 14):

instance Monad [] where
    return x = [x]
    xs >>= f = concat (map f xs)
    xs >> f = concat (map (\_ -> f) xs)
    fail _ = []

Therefore, a list comprehension basically builds a singleton list for every element selected in the list comprehension and concatenates them. If a pattern match fails at some step, the result of the "fail" function is used instead. In other words, the "Just x" pattern doesn't match so [] is used as a placeholder until 'concat' is called. That explains why the "Nothing" appears to be skipped.

What I don't understand is, how does Haskell know to call the "fail" function? Is it "compiler magic", or functionality that you can write yourself in Haskell? Is it possible to write the following "select" function to work the same way as a list comprehension?

select :: (a -> b) -> [a] -> [b]
select (Just x -> x) myList       -- how to prevent the lambda from raising an error?
[1,2,3]

解决方案

While implemenatations of Haskell might not do it directly like this internally, it is helpful to think about it this way :)

[x | Just x <- myList]

... becomes:

do
    Just x <- myList
    return x

... which is:

myList >>= \(Just x) -> return x

As to your question:

What I don't understand is, how does Haskell know to call the "fail" function?

In do-notation, if a pattern binding fails (i.e. the Just x), then the fail method is called. For the above example, it would look something like this:

myList >>= \temp -> case temp of
    (Just x) -> return x
    _        -> fail "..."

So, every time you have a pattern-match in a monadic context that may fail, Haskell inserts a call to fail. Try it out with IO:

main = do
    (1,x) <- return (0,2)
    print x -- x would be 2, but the pattern match fails

这篇关于为什么模式匹配失败时,Haskell列表解析会导致错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆