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.