为什么使用lambda而不是模式匹配?

tof*_*tis 5 lambda parsing haskell

我正在观看有关解析器的教程,包括haskell https://www.youtube.com/watch?v=9FGThag0Fqs.讲座从定义一些非常基本的解析器开始.这些将在以后一起用于创建更复杂的解析器.其中一个基本解析器是item.这用于从我们正在解析的字符串中提取字符.

所有解析器都具有以下类型:

type Parser a = String -> [(a, String)]                                         
Run Code Online (Sandbox Code Playgroud)

解析器定义如下:

item :: Parser Char                                                             
item = \inp -> case inp of                                                      
                    [] -> []                                                
                    (x:xs) -> [(x,xs)]
Run Code Online (Sandbox Code Playgroud)

我不习惯这种语法,所以它看起来很奇怪.我会写的:

item' :: Parser Char                                                            
item' [] = []                                                                   
item' (x:xs) = [(x,xs)]
Run Code Online (Sandbox Code Playgroud)

在ghci中测试它表明它们是相同的:

*Main> item ""
[]
*Main> item "abc"
[('a',"bc")]
*Main> item' ""
[]
*Main> item' "abc"
[('a',"bc")]
Run Code Online (Sandbox Code Playgroud)

讲师做了一个简短的评论,认为它看起来更清晰,但我不同意.所以我的问题是:

它们确实完全相同吗?为什么lambda版本更清晰?

chi*_*chi 11

我相信这来自于写作的常见做法

f :: Type1 -> ... -> Typen -> Result
f x1 ... xn = someResult
Run Code Online (Sandbox Code Playgroud)

我们n在类型中具有完全功能箭头,并且n在等式的左侧具有完全参数.这使得关联类型和形式参数变得容易.

如果Result是函数的类型别名,那么我们可以写

f :: Type1 -> ... -> Typen -> Result
f x1 ... xn y = something
Run Code Online (Sandbox Code Playgroud)

要么

f :: Type1 -> ... -> Typen -> Result
f x1 ... xn = \y -> something
Run Code Online (Sandbox Code Playgroud)

后者遵循上述惯例:n箭头,n左侧的变量.此外,在右侧我们有一些类型Result,使其更容易发现.前者却没有,并且在快速阅读代码时可能会错过额外的参数.

此外,这种样式可以很容易地转换Result为newtype而不是类型别名:

newtype Result = R (... -> ...)

f :: Type1 -> ... -> Typen -> Result
f x1 ... xn = R $ \y -> something
Run Code Online (Sandbox Code Playgroud)

发布的item :: Parser Char代码是此样式的实例n=0.

  • 我完全同意新类型的东西.你至少希望你的解析器成为一个Functor和Applicative,所以你需要newtype,所以只需要很少的编辑就可以为它做好准备是一件好事. (2认同)