我真的不懂代码
extent = [xbins.min(), xbins.max(), ybins.min(), ybins.max()]
fig, ax = plt.subplots()
mesh = ax.imshow(values, extent=extent, origin='lower', aspect='auto',
cmap='gist_earth', norm=LogNorm())
ax.axis('tight')
ax.set(title='Log Normalized Plot of Values')
fig.colorbar(mesh)
plt.show()
以防:
我可以排序/更改agruments“id xs []”的位置吗?
myReverse'' :: [a] -> [a]
myReverse'' xs = foldr (\x fId empty -> fId (x : empty)) id xs []
我昨天读了一本书http://learnyouahaskell.com/higher-order-functions#lambdas
myReverse'' xs = foldr (\x fId empty -> fId (x : empty)) xs id []
这个解释对我来说是可以理解的。
左侧折叠的二元函数将累加器作为第一个参数,将当前值作为第二个参数(所以\ acc x - > ...)
或者我可以写为
elem' :: (Eq a) => a -> [a] -> Bool
elem' y ys = foldl (\acc x -> if x == y then True else acc) False ys
任何人,可以帮助/指导/解释我吗?
非常感谢!
答案 0 :(得分:1)
关键是如何使用差异列表。让我们写一些明确的转换:
revCons
请注意{{1}}有三个参数,虽然它的签名实际上只表示两个:差异列表实际上是一个函数类型,但您可以将这些函数视为具体列表的抽象优化表示。
答案 1 :(得分:1)
我喜欢理解这些“带有foldr
的反向列表”问题的方法是将其拆分成几部分,然后应用"Foldr is made of monoids"的课程。别担心,这并不像听起来那么可怕。
首先,让我们注意reverse
可以这样实现:
my_reverse xs = foldl (flip (:)) xs []
这是我们问题的第一个简化:如果我们能够弄清楚如何用foldl
来编写foldr
,那么我们可以将该解决方案插入my_reverse
并完成用它。
现在,foldr
的标准类型签名是:
foldr :: (a -> r -> r) -> r -> [a] -> r
但是参数的顺序并不重要,所以让我们以这种方式重新排列事物(也抛出一些隐含的括号),然后我们将它与map
进行比较:
my_foldr :: (a -> (r -> r)) -> [a] -> (r -> r)
map :: (a -> b ) -> [a] -> [b]
一旦看到这封信,就不难发现我们可以这样写my_foldr
:
my_foldr :: (a -> (r -> r)) -> [a] -> (r -> r)
my_foldr f as = compose (map f as)
where compose :: [r -> r] -> (r -> r)
compose = foldr (.) id
以下列方式考虑这个问题:
map
操作正在将列表的每个元素转换为我们应用于r
值的转换的“步骤”。compose
函数使用结果列表“步骤”并使用.
运算符将它们连接在一起。现在的诀窍是我们可以用一个小小的变化来编写foldl
对应物:
my_foldl :: (a -> (r -> r)) -> [a] -> (r -> r)
my_foldl f as = compose (map f as)
where compose :: [r -> r] -> (r -> r)
compose = foldr (flip (.)) id
{- Example:
>>> my_foldl (:) [1..3] []
[3,2,1]
-}
我所做的就是将(.)
更改为flip (.)
!请注意my_foldl
是根据map
和foldr
写的......但map
也可以用foldr
重写:
my_map :: (a -> b) -> [a] -> [b]
my_map f = foldr (\a bs -> f a : bs) []
因此,我们最终得到的解决方案与您尝试理解的解决方案不同且更长,但希望它具有启发性。
答案 2 :(得分:0)
如果你这样做:
Prelude :t \x fId empty -> fId (x : empty)
你会得到:
\x fId empty -> fId (x : empty) :: a -> ([a] -> t) -> [a] -> t
此处的此功能类型相当于:
a -> ([a] -> t) -> ([a] -> t)
表示一个函数(二元函数),它接受两个参数(第二个参数是一个函数,即[a] -> t
)并返回一个函数(即[a] -> t
)。
这个二元函数匹配foldr
所取的第一个参数(即a -> b -> b
)。
换句话说,foldr (\x fId empty -> fId (x : empty))
有两个参数:一个函数和一个列表,并返回一个函数。
Prelude> :t foldr (\x fId empty -> fId (x : empty))
foldr (\x fId empty -> fId (x : empty))
:: ([a] -> t) -> [a] -> [a] -> t
举个例子:foldr (\x fId empty -> fId (x : empty)) id [1, 2, 3]
。
步骤1:将3
和id
作为参数传递给匿名二进制函数。像\empty -> id (3 : empty)
这样的函数将作为新的累加器值返回。
第2步:将2
和\empty -> id (3 : empty)
传递给匿名二进制函数。并返回\empty -> id (3 : (2 : empty))
。
步骤3:将1
和\empty -> id (3 : (2 : empty))
传递给匿名二进制函数。并返回\empty -> id (3 : (2 : (1 : empty)))
。
因此foldr (\x fId empty -> fId (x : empty)) id [1, 2, 3]
会产生类似\empty -> id (3 : (2 : (1 : empty)))
的函数。
如果您将\empty -> id (3 : (2 : (1 : empty)))
应用于[]
,那么它会为您提供[3, 2, 1]
。
这意味着foldr (\x fId empty -> fId (x : empty)) id [1, 2, 3] []
会产生[3, 2, 1]
。