如何根据输入返回调用另一个函数的函数?

时间:2015-04-21 21:06:00

标签: haskell ghci

我对Haskell来说真的很新,我需要返回一个"已经修改过"输入的功能。

我猜你不能复制和修改原始函数(基于某些条件),所以你必须直接实现自己的行为,然后调用原始函数?

这是我的方法:

switchFirstEgg eggCarton = if eggCarton 1 == 0
                                then switchedCarton where switchedCarton position = if position == 1 then 2 else eggCarton position
                                else if eggCarton 1 == 1
                                        then switchedCarton where switchedCarton position = if position == 1 then 0 else eggCarton position
                                        else if eggCarton 1 == 2
                                                then switchedCarton where switchedCarton position = if position == 1 then 1 else eggCarton position
                                                else switchedCarton where switchedCarton position = eggCarton position

我从GHCI得到的错误是

  

haskell / eggcartons.hs:42:54:解析输入'where'的错误

指向第一个where之后的第一个单词。

(供参考:我还尝试在http://pastebin.com/2wTqAqpm设置更多括号,我尝试使用警卫http://pastebin.com/RVm28Y7n进行操作,但这只是在没有深入理解的情况下使情况变得更糟?至少警卫在这里为我工作http://pastebin.com/uQeFwLU5

我在Haskell中搜索了返回的函数,但是我只得到了一些我用where事件的随机信息。

我的观念是对的吗?这只是一个小错误吗?

对于有关返回函数语法的进一步阅读的任何帮助也非常感谢!

2 个答案:

答案 0 :(得分:6)

首先让我们稍微阅读......

switchFirstEgg ec
     = if ec 1 == 0
        then sc where sc pos = if pos == 1
                                then 2
                                else ec pos
        else if ec 1 == 1
              then sc where sc pos = if pos == 1
                                      then 0
                                      else ec pos
              else if ec 1 == 2
                    then sc where sc pos = if position == 1
                                            then 1
                                            else ec pos
                    else sc where sc pos = ec pos

现在。 where每个定义只能使用一次,即在您撰写switchFirstEgg _ = ...之后,您可以关注where,该=sc之后的所有内容有效。或者,您可以在if的其中一个定义之后更多地在本地使用。但是你不能把它放在代码中间的任何地方,比如在let分支中。

非常相似的switchFirstEgg ec = if ec 1 == 0 then let sc pos = if pos == 1 then 2 else ec pos in sc else if ec 1 == 1 then let sc pos = if pos == 1 then 0 else ec pos in sc else if ec 1 == 2 then let sc pos = if pos == 1 then 1 else ec pos in sc else let sc pos = ec pos in sc 结构允许这样做,所以你尝试的最简单的翻译是

sc

但那很笨重。如果仅在定义后立即使用一次,您就不需要使用名称定义switchFirstEgg ec = if ec 1 == 0 then \pos -> if pos == 1 then 2 else ec pos else if ec 1 == 1 then \pos -> if pos == 1 then 0 else ec pos else if ec 1 == 2 then \pos -> if pos == 1 then 1 else ec pos else \pos -> ec pos 。这是一个明确的lambda应用程序:

if

更好,但case的这一链显然更好地表达为switchFirstEgg ec = case ec 1 of 0 -> \pos -> if pos == 1 then 2 else ec pos 1 -> \pos -> if pos == 1 then 0 else ec pos 2 -> \pos -> if pos == 1 then 1 else ec pos _ -> \pos -> ec pos 个子句的单个集合。

pos

此时很明显switchFirstEgg ec pos = case ec 1 of 0 -> if pos == 1 then 2 else ec pos 1 -> if pos == 1 then 0 else ec pos 2 -> if pos == 1 then 1 else ec pos _ -> ec pos 绑定非常统一,所以我们可以将它们全部向上移动:

if

我们在模式匹配后立即switchFirstEgg ec pos = case ec 1 of 0 | pos == 1 -> 2 1 | pos == 1 -> 0 2 | pos == 1 -> 1 _ -> ec pos 。现在这非常适合警卫

pos

或者,您可以在考虑ec 1之前立即在switchFirstEgg ec 1 = case ec 1 of 0 -> 2 1 -> 0 2 -> 1 n -> n switchFirstEgg ec pos = ec pos 上进行匹配:

{{1}}

答案 1 :(得分:3)

看看这是否符合您的要求:

switchFirstEgg eggCarton = 
  switchedCarton
  where switchedCarton = case (eggCarton 1) of
                         0 -> \position -> if position == 1
                                           then 2
                                           else eggCarton position
                         1 -> \position -> if position == 1
                                           then 0
                                           else eggCarton position
                         2 -> \position -> if position == 1
                                           then 1
                                           else eggCarton position
                         _ -> \position -> eggCarton position

在函数定义中只能有一个where子句(尽管where子句中的函数定义可以有自己的where子句。)

相关问题