【问题标题】:Understanding a let-expression in Haskell理解 Haskell 中的 let 表达式
【发布时间】:2019-01-29 02:24:47
【问题描述】:

我是 Haskell 的新手,目前正在为考试而学习它。我一直从learnyouahaskell学习它。我不明白 group 函数中的以下 let 表达式。

splitWhen :: (a -> Bool) -> [a] -> ([a],[a])    
splitWhen p xs = (takeWhile (not . p) xs, dropWhile (not . p) xs)

group :: (Eq a) => [a] -> [[a]]
group [] = []
group (x:xs) = let (group1, rest) = splitWhen (/=x) xs
                   in (x:group1) : group rest

我知道 splitWhen 做了什么:splitWhen even [1,2,3] => ([1],[2,3])

我知道函数组产生以下内容:

group [1,1,2,1,3,3,3] => [[1,1],[2],[1],[3,3,3]]

我不明白它是如何工作的。有人可以向我解释一下吗? 谢谢。

【问题讨论】:

  • 您具体询问的是哪一部分? (/=x)?
  • 整个 let (group1, rest) = splitWhen (/=x) xs in (x:group1) : group rest
  • 你需要查找解构来找出let 之后的部分,以及in 之后的部分的递归和 cons 构造函数。不过,解释这些行的全部内容过于宽泛。

标签: haskell


【解决方案1】:

let 表达式是用于立即应用匿名函数的语法糖。也就是说,

let (group1, rest) = splitWhen (/=x) xs
    in (x:group1) : group rest

等价于

(\(group1, rest) -> (x:group1) : group rest) (splitWhen (/=x) xs)

换句话说,let 反转了函数体和函数参数的位置。比较

let name =  value in body
(  \name -> body  )  value

【讨论】:

  • 所以我首先申请splitWhen,这会生成一个列表元组([a],[a])。为此,我应用了 lambda 函数,它将 x 添加到元组的第一个列表并迭代到第二个。我收到了吗?
  • 基本上。但请记住,Haskell 是惰性的,因此只有在有人开始使用 group 的返回值时才会调用 splitWhen。最好说group1rest 绑定到splitWhen 返回的元组元素,并在let 表达式的主体中使用以生成所需的列表。
  • 好的,非常感谢。
【解决方案2】:
let (group1, rest) = splitWhen (/=x) xs

这调用splitWhen (/=x) xs 并在返回的元组上使用模式匹配将其分配给(group1, rest)。那么这些值可以用在

in (x:group1) : group rest

计算函数的最终结果。

您可以将其实现为where 子句并获得相同的行为:

group (x:xs) = (x:group1) : group rest
    where (group1, rest) = splitWhen (/=x) xs

【讨论】:

    猜你喜欢
    • 2015-07-26
    • 2018-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-11
    • 2014-01-01
    • 2018-06-24
    • 1970-01-01
    相关资源
    最近更新 更多