微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

squareOn 的文件夹 - Haskell

如何解决squareOn 的文件夹 - Haskell

在我的讲座中,我们必须定义函数 squareOn 使得

1

带有foldr。 答案是

 squareOn :: (Eq a,Num a) => [a] -> a -> a        
 squareOn = foldr (\x acc y -> if y == x then x*x else acc y) id

我不明白 foldr 是如何工作的,但我是 Haskell 中 lambda 表达式的新手。 acc 是 Haskell 的任何类型的函数吗?如果有人能解释 squareOn 是如何工作的,那就太好了。 :)

解决方法

这是 foldr 的一种高级用法。通常,我们看到 foldr 用于

fun xs = foldr (\x acc -> something using x and acc) base xs

或等效

fun = foldr (\x acc -> something using x and acc) base

对应如下递归函数:

fun []     = base
fun (x:xs) = something using x and acc
   where acc = fun xs

您的案例是这种用法的一个特例,其中 baseaccsomething using x and acc函数。也就是说,我们有

fun []     = \y -> base'
fun (x:xs) = \y -> something using x,acc,y
   where acc = \y -> fun xs y

回到foldr,我们得到

fun = foldr (\x acc -> \y -> something using x,y) (\y -> base')

也可以写成

fun = foldr (\x acc y -> something using x,y) (\y -> base')

一个令人困惑的三参数函数似乎被传递给 foldr

您的具体情况,

squareOn = foldr (\x acc y -> if y == x then x*x else acc y) id

对应显式递归:

squareOn []     = id
squareOn (x:xs) = \y -> if y == x then x*x else acc y
   where acc = \y -> squareOn xs y

squareOn []     y = y
squareOn (x:xs) y = if y == x then x*x else squareOn xs y

你应该能够理解。

,

让我们在没有 lambda 的情况下定义这个函数。

squareOn :: (Eq a,Num a) => [a] -> a -> a
squareOn = foldr f id
  where
    f x acc = g
      where
        g y | x == y = x * x
            | otherwise = acc y

现在变成了 foldr 通常的样子。它需要一个带有两个参数 f 和一个初始值 id 的函数。

当您将 [2,4] 传递给 squareOn 时,它会根据 foldr f id [2,4] 的定义扩展为 f 2 (f 4 id),然后是 foldr

f 4 id 返回一个接受一个参数 y 的函数,如果 4 * 4y,它返回 4,否则返回 id y。我们将此函数称为 p

p y | 4 == y = 4 * 4
    | otherwise = id y

现在,f 2 (f 4 id) 返回一个带有一个参数 y 的函数,如果 2 * 2y,它返回 2,否则返回 p y .当您将其命名为 q 时,它会是这样的。

q y | 2 == y = 2 * 2
    | otherwise = p y

例如,squareOn [2,4] 3 等价于 q 3

,

谁跳过了那些明确的论点,只会让自己不必要地更难学习这些东西。这完全是肤浅的。添加由类型签名指定的显式参数,给我们

squareOn :: (Eq a,Num a) => [a] -> a -> a
squareOn      = foldr (\x acc y -> if y == x then x*x else acc y) id
squareOn xs   = foldr (\x acc y -> if y == x then x*x else acc y) id xs
squareOn xs y = foldr (\x acc y -> if y == x then x*x else acc y) id xs y
squareOn xs y = foldr g id xs y   where { g x acc y | y == x    = x*x 
                                                    | otherwise = acc y }
squareOn xs y = (case xs of { 
    []      -> id ;
    (x:xs2) -> g x (foldr g id xs2)
                          })  y   where { g x acc y | y == x    = x*x 
                                                    | otherwise = acc y }

现在我们可以看到这里发生的一切,而不是必须记住所有这些。有下棋,然后是下蒙眼象棋,如果你能看到,为什么要蒙着眼睛玩呢?

所以现在很明显 passing that y around(*) from call to call unchanged 实际上在这里没有任何意义,因为它是相同的 {{1 }},并且它已经在范围内:

y

简化回来

squareOn xs y = (case xs of { 
    []      -> y  ;
    (x:xs2) -> g x (foldr g y  xs2)
                          })      where { g x acc   | y == x    = x*x 
                                                    | otherwise = acc   }

并且要像你的原始代码一样简短而无意义,

squareOn xs y = foldr g y  xs     where { g x acc   | y == x    = x*x 
                                                    | otherwise = acc   }
{- cf.
squareOn xs y = foldr g id xs y   where { g x acc y | y == x    = x*x 
                                                    | otherwise = acc y } -}

或者可以简化为

squareOn      = flip (foldr g)    where { g x acc   | y == x    = x*x 
                                                    | otherwise = acc   }

进一步到具有嵌套一元工作器的工作器/包装器,以您更清楚为准。

只有在没有嵌套作用域的语言(如 Prolog)中才真正需要传递未更改的数量以使其在作用域内。

(*)(所以你要求的关于这种技术如何工作的完整解释实际上在链接的答案中)。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?