我正在尝试解决最大子序列和问题,并想出了一个聪明的解决方案。
您调用包装函数
但是,那个包装函数真的让我感到不舒服。我喜欢在Haskell中,如果你足够坚持,你可以在一行上编写整个程序,以真正说明一个程序实际上只是一个大表达式。因此,我想尝试消除额外的挑战。
现在,我遇到了经典问题:如何进行匿名递归?当您无法给函数命名时,如何进行递归?幸运的是,计算机之父们早在很久以前就解决了这个问题,他们发现了固定点组合器,其中最流行的是Y组合子。
我尝试过多种方式来设置Y组合子,但它们都无法通过编译器。
msss :: (Ord a, Num a) => [a] -> a
msss = f 0 0
f gmax _ [] = gmax
f gmax lmax (x:xs) =
let g = max (lmax + x)
in f (g gmax) (g 0) xs
您调用包装函数
msss
,它然后调用f
,后者实际上执行工作。
该解决方案很好,据我所知,可以正常工作。如果由于某种原因我必须在生产代码中解决最大子序列和问题,那么我会这样做。但是,那个包装函数真的让我感到不舒服。我喜欢在Haskell中,如果你足够坚持,你可以在一行上编写整个程序,以真正说明一个程序实际上只是一个大表达式。因此,我想尝试消除额外的挑战。
现在,我遇到了经典问题:如何进行匿名递归?当您无法给函数命名时,如何进行递归?幸运的是,计算机之父们早在很久以前就解决了这个问题,他们发现了固定点组合器,其中最流行的是Y组合子。
我尝试过多种方式来设置Y组合子,但它们都无法通过编译器。
msss' :: [Int] -> Int
msss' = (\y f x -> f (y y f) x)
(\y f x -> f (y y f) x)
(\g' gmax lmax list -> if list == []
then gmax
else g' (max gmax lmax + head list)
(max 0 lmax + head list)
tail list)
仅仅给出
Prelude> :l C:\maxsubseq.hs
[1 of 1] Compiling Main ( C:\maxsubseq.hs, interpreted )
C:\maxsubseq.hs:10:29:
Occurs check: cannot construct the infinite type:
t0 = t0 -> (([Int] -> Int) -> [Int] -> Int) -> [Int] -> Int
In the first argument of `y', namely `y'
In the first argument of `f', namely `(y y f)'
In the expression: f (y y f) x
C:\maxsubseq.hs:11:29:
Occurs check: cannot construct the infinite type:
t0 = t0 -> (([Int] -> Int) -> [Int] -> Int) -> [Int] -> Int
In the first argument of `y', namely `y'
In the first argument of `f', namely `(y y f)'
In the expression: f (y y f) x
C:\maxsubseq.hs:12:14:
The lambda expression `\ g' gmax lmax list -> ...'
has four arguments,
but its type `([Int] -> Int) -> [Int] -> Int' has only two
In the second argument of `\ y f x -> f (y y f) x', namely
`(\ g' gmax lmax list
-> if list == [] then
gmax
else
g' (max gmax lmax + head list) (max 0 lmax + head list) tail list)'
In the expression:
(\ y f x -> f (y y f) x)
(\ y f x -> f (y y f) x)
(\ g' gmax lmax list
-> if list == [] then
gmax
else
g' (max gmax lmax + head list) (max 0 lmax + head list) tail list)
In an equation for `msss'':
msss'
= (\ y f x -> f (y y f) x)
(\ y f x -> f (y y f) x)
(\ g' gmax lmax list
-> if list == [] then
gmax
else
g' (max gmax lmax + head list) (max 0 lmax + head list) tail list)
Failed, modules loaded: none.
从f (y y f)
改为f (y f)
只会得到
C:\maxsubseq.hs:11:29:
Couldn't match expected type `[Int] -> Int'
with actual type `[Int]'
Expected type: (([Int] -> Int) -> t1 -> t0) -> t2 -> t0
Actual type: ([Int] -> Int) -> t1 -> t0
In the first argument of `y', namely `f'
In the first argument of `f', namely `(y f)'
Failed, modules loaded: none.
我尝试采用不同的方法,仅在外部定义组合器,然而这仍然无法工作,并且并不真正满足我在一个表达式中完成它的挑战。
y f = f (y f)
msss' :: [Int] -> Int
msss' = y (\g' gmax lmax list -> if list == []
then gmax
else g' (max gmax lmax + head list)
(max 0 lmax + head list)
tail list)
你能发现我做错了什么吗?我很茫然。抱怨构建无限类型真的让我很生气,因为我认为Haskell就是这样的语言。它有无限的数据结构,那么为什么会有无限类型的问题呢?我怀疑这与那个显示无类型lambda演算不一致的悖论有关。但我不确定。如果有人能澄清一下就好了。
此外,我认为递归总是可以用fold函数表示的。有人能向我展示如何只使用fold来实现递归吗?但要求代码仍然是单个表达式。
0 0
即可。 - is7s