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

Haskell 如何根据输入返回调用另一个函数的函数?,haskell,ghci,Haskell,Ghci,我对Haskell真的很陌生,我需要返回一个修改了输入函数的函数 我猜你不能根据某些条件复制和修改原始函数,所以你必须直接实现自己的行为,然后调用原始函数 这是我的方法: switchFirstEgg eggCarton = if eggCarton 1 == 0 then switchedCarton where switchedCarton position = if position == 1 then 2 else eggC

我对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

参考:我也试着在这里设置更多的括号,我试着用护卫来做,但这只会让事情变得更糟,而没有经过深思熟虑的理解?至少警卫在这里为我工作

我在Haskell中搜索返回函数,但我只得到了一些随机信息,这些信息和我在哪里做的事情有关

我的想法正确吗?这只是一个小错误吗


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

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

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子句。

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

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子句。

首先让我们让它更具可读性

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
现在。其中每个定义只能使用一次,即在您编写switchFirstEgg=。。。您可以遵循where,该where对之后的所有内容都有效=。或者,您可以更本地地使用SIS的那些定义中的一个,但不能在代码的中间粘贴,如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,则实际上不需要使用名称来定义sc。这是lambdas的一个明确应用程序:

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
更好,但是if链显然更好地表示为case子句的单个集合

此时,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
在模式匹配之后,我们有ifs。这是一款非常适合护卫的装备:

或者,您可以在考虑ec 1之前,立即在pos上匹配:


首先,让我们让这有点可读性

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
现在。其中每个定义只能使用一次,即在您编写switchFirstEgg=。。。您可以遵循where,该where对之后的所有内容都有效=。或者,您可以更本地地使用SIS的那些定义中的一个,但不能在代码的中间粘贴,如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,则实际上不需要使用名称来定义sc。这是lambdas的一个明确应用程序:

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
更好,但是if链显然更好地表示为case子句的单个集合

此时,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
在模式匹配之后,我们有ifs。这是一款非常适合护卫的装备:

或者,您可以在考虑ec 1之前,立即在pos上匹配:


我不同意用ec替换eggCarton,用sc替换switchedCarton有助于提高可读性。否则,这是一个很好的答案。@WolfeFan:嗯,在这种情况下,原始版本很难阅读,因为它的宽度太大了。当然,将变量缩短为两个字母并不总是一个好主意,但是任何经常被写八次的名字都应该保持简短,或者至少在局部使用缩写。回答得好。请注意,与前面的备选方案不同,如果pos为1且ec 1为3,则最后一个答案将崩溃,因为该情况并非详尽无遗。当然,我们可以在箱子里加上->ec pos来防止这种情况。@chi:对。或者n->n,我更喜欢它,因为它只计算ec pos≡ 欧共体1次。补充回答。感谢您的详细解释,这很有帮助!:但我真的很难理解这些变量名;如果你愿意,你可以把它改回较长的,或者我也可以这样做,因为我认为这对其他人来说也会更容易!减少缩进确实有助于提高可读性。我不同意用ec替换eggCarton,用sc替换switchedCarton有助于提高可读性。否则,这是一个很好的答案。@WolfeFan:嗯,在这种情况下,原始版本很难阅读,因为它的宽度太大了。当然,将变量缩短为两个字母并不总是一个好主意,但任何名称都是wr
经常写八次应该保持简短,或者至少在本地用缩写来表示简短。回答得好。请注意,与前面的备选方案不同,如果pos为1且ec 1为3,则最后一个答案将崩溃,因为该情况并非详尽无遗。当然,我们可以在箱子里加上->ec pos来防止这种情况。@chi:对。或者n->n,我更喜欢它,因为它只计算ec pos≡ 欧共体1次。补充回答。感谢您的详细解释,这很有帮助!:但我真的很难理解这些变量名;如果你愿意,你可以把它改回较长的,或者我也可以这样做,因为我认为这对其他人来说也会更容易!减少缩进确实有助于提高可读性。