一个非常基本的Haskell查询

时间:2012-02-02 22:56:39

标签: haskell

我非常想知道Haskell的世界,没有任何事先与此有关的背景。原因是我遇到了一个我试图解决的难题似乎是基于haskell代码。我相信我所追求的是一个整数。

我想要做的是以下

let a = \x -> x (\y z -> (\y z -> (\y z -> (\y z -> (\y z -> (\y z -> (\y z -> (\y z -> (\y z -> (\y z -> (\y z -> (\y z -> y (y z)) (\x -> y (y (y (y (y (y (y x))))))) z) (\x -> y (y (y (y (y (y (y (y (y x))))))))) z) y (y z)) (\x -> y (y (y (y x)))) z) y (y z)) (\x -> y (y (y (y x)))) z) (\x -> y (y (y (y (y x))))) z) y (y z)) (\x -> y (y (y (y (y (y (y (y x)))))))) z) (\x -> y (y (y (y (y (y (y (y x)))))))) z) (\x -> y (y (y (y (y (y (y (y x)))))))) z) (\y z -> (\y z -> (\y z -> (\y z -> (\y z -> (\y z -> (\y z -> (\y z -> y (y z)) (\x -> y (y (y (y (y (y (y (y (y x))))))))) z) y (y z)) (\x -> y (y (y (y (y x))))) z) (\x -> y (y (y (y (y (y x)))))) z) y (y z)) (\x -> y (y x)) z) (\x -> y (y (y (y (y (y x)))))) z)

a (1+) 0

这将返回以下错误消息

<interactive>:1:4:
No instance for (Num
                   (((t20 -> t20) -> t20 -> t20) -> (t20 -> t20) -> t20 -> t20))
  arising from the literal `1'
Possible fix:
  add an instance declaration for
  (Num (((t20 -> t20) -> t20 -> t20) -> (t20 -> t20) -> t20 -> t20))
In the first argument of `(+)', namely `1'
In the first argument of `a', namely `(1 +)'
In the expression: a (1 +) 0

<interactive>:1:8:
No instance for (Num (t20 -> t20))
  arising from the literal `0'
Possible fix: add an instance declaration for (Num (t20 -> t20))
In the second argument of `a', namely `0'
In the expression: a (1 +) 0
In an equation for `it': it = a (1 +) 0

简单的问题 - 我需要做些什么来完成这项工作?

请记住,目前我对此一无所知。我会非常感谢任何人都能给我的任何帮助!

编辑:

我确实得到了类似的表达方式:

let x = \s z -> ((\s z -> ((\s z -> ((\s z -> ((\s z -> (((\s z -> ((\s z -> (s . s) z) . (\s z -> (s . s . s) z)) s z) s) . ((\s z -> s z) s)) z) . (\s z -> (((\s z -> ((\s z -> ((\s z -> (s . s) z) . (\s z -> (s . s) z)) s z) . (\s z -> (s . s . s) z)) s z) s) . ((\s z -> s z) s)) z)) s z) . (\s z -> (((\s z -> ((\s z -> (s . s) z) (\s z -> ((\s z -> (s . s) z) . (\s z -> (s . s) z)) s z)) s z) s) . ((\s z -> (s . s . s) z) s)) z)) s z) . (\s z -> (((\s z -> ((\s z -> (s . s) z) (\s z -> ((\s z -> (s . s) z) . (\s z -> (s . s) z)) s z)) s z) s) . ((\s z -> (((\s z -> ((\s z -> (s . s) z) . (\s z -> (s . s . s) z)) s z) s) . ((\s z -> s z) s)) z) s)) z)) s z) . (\s z -> (((\s z -> ((\s z -> ((\s z -> (s . s) z) . (\s z -> (s . s . s) z)) s z) . (\s z -> (((\s z -> ((\s z -> ((\s z -> (s . s) z) . (\s z -> (s . s) z)) s z) . (\s z -> (s . s . s) z)) s z) s) . ((\s z -> s z) s)) z)) s z) s) . ((\s z -> s z) s)) z)) s z

x (1+) 0

返回整数3141593

2 个答案:

答案 0 :(得分:14)

好的,让我们把它分解成更小的部分。事实上,这种表达只是线噪声。

首先,请注意,对于(\x -> y (y (y (y (y (y x))))))的不同数量的应用程序,有很多类似于y的内容。所以让我们抽象出来:

(^^) :: (a -> a) -> Int -> (a -> a)
y ^^ 0 = id
y ^^ n = y . (y ^^ (n - 1))

所以(\x -> y (y (y (y (y (y x))))))只是y ^^ 6

这看起来像这样:

let a = \x -> x 
              (\y z -> 
                (\y z -> 
                  (\y z -> 
                    (\y z -> 
                      (\y z -> 
                        (\y z -> 
                          (\y z -> 
                            (\y z -> 
                              (\y z -> 
                                (\y z -> 
                                  (\y z -> 
                                    (\y z -> y (y z)) (y ^^ 7) z) 
                                  (y ^^ 9) z) 
                                y (y z)) 
                              (y ^^ 4) z) 
                            y (y z)) 
                          (y ^^ 4) z) 
                        (y ^^ 5) z) 
                      y (y z)) 
                    (y ^^ 8) z) 
                  (y ^^ 8) z) 
                (y ^^ 8) z) 
              (\y z -> (\y z -> (\y z -> (\y z -> (\y z -> (\y z -> (\y z -> (\y z -> y (y z)) (y ^^ 9) z) y (y z)) (y ^^ 5) z) (y ^^ 6) z) y (y z)) (y ^^ 2) z) (y ^^ 6) z)

仍然不是很好,但让我们专注于那个巨大的楔子的尖端

(\y z -> y (y z)) (y ^^ 7) z 

(\y z -> y (y z))只是(\y -> y ^^ 2),所以让我们把它放在:

(\y -> y ^^ 2) (y ^^ 7) z 

使用替换,这给了我们

((y ^^ 7) ^^ 2) z

这是我展示我的预知命名技能的地方,并且使(y ^^ 7) ^^ 2 == (y ^^ 14)的声明变得无比(但真实!)。也就是说,在英语中,如果我们连续七次调用y,连续两次调用,这与连续调用y十四次相同。

所以现在我们离开了

(y ^^ 14) z

如果我们退后一点,那就在

(\y z -> (y ^^ 14) z) (y ^^ 9) z

相同
(\y -> y ^^ 14) (y ^^ 9) z

相同
((y ^^ 9) ^^ 14) z

相同
(y ^^ 126) z

依此类推。

偶尔会出现像

这样的情况
(\y -> y ^^ n) y (y z)

这真的只是

(y ^^ n) (y z)

或者

(y ^^ (n+1)) z

无论如何,您可以使用这些方法继续简化代码,直到

let a = \x -> x (\y -> y ^^ 2652672) (\y -> y ^^ 6852)

或类似的东西,我可能已经搞砸了y s。

但这就像它会变得那么简单。

现在你可以传递一个像a $ \f g -> f (+1) 0 + g (+1) 0这样的函数,它只会加1到0 2652672次,并加1到0 6852次,并对结果求和。正如我们目前实施的那样(^^),这需要很长时间才能给出2659524。

答案 1 :(得分:0)

a的类型相当复杂,您的参数不适合该函数:

Prelude> :t a
a :: (((t1 -> t1) -> t1 -> t1) -> ((t2 -> t2) -> t2 -> t2) -> t)
     -> t

由于(1+) :: Num a => a -> a的类型不是(((t1 -> t1) -> t1 -> t1) -> ((t2 -> t2) -> t2 -> t2) -> t)形式,因此它不是a的有效参数。

很难说问题来自何处,因为不清楚表达式应该做什么或者如何导出它。也许某些括号错误或隐藏外部lambda参数的嵌套lambda表达式的参数名称导致了这个问题。