Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell中的递归混淆_Haskell_Recursion - Fatal编程技术网

Haskell中的递归混淆

Haskell中的递归混淆,haskell,recursion,Haskell,Recursion,我希望有人能帮我找出我的错误所在。调用g34002(M.empty,0)[,我希望结果是[[2,1,0,1]]。相反,我看到的是[[2,1,0,1],[2,1,0,1]] 程序应该通过每次向列表中添加不同的数字来累积长度为m的不同数字模式,当到达n-1时返回向下,当到达0时返回向上。表观问题发生在中间,当函数被上下方向递归调用时。p> 如果我这样注释第11行: else g n m (digitCount + 1) (lastDigit + 1) (hash',hashCount') (last

我希望有人能帮我找出我的错误所在。调用
g34002(M.empty,0)[
,我希望结果是
[[2,1,0,1]]
。相反,我看到的是
[[2,1,0,1],[2,1,0,1]]

程序应该通过每次向列表中添加不同的数字来累积长度为
m
的不同数字模式,当到达
n-1
时返回向下,当到达
0
时返回向上。表观问题发生在中间,当函数被上下方向递归调用时。p> 如果我这样注释第11行:

else g n m (digitCount + 1) (lastDigit + 1) (hash',hashCount') (lastDigit:digits)
  -- g n m (digitCount + 1) (lastDigit - 1) (hash',hashCount') (lastDigit:digits)
我得到了正确的结果
[]

当注释掉第11行并将第10行修改为:

else g n m (digitCount + 1) (lastDigit - 1) (hash',hashCount') (lastDigit:digits)
同样,正确的结果
[[2,1,0,1]]

为什么在使用
++
操作符调用
g
两次时,我得到的是两个
[2,1,0,1]
?在我看来,
g
中的每个结果都应该是不同的,因为在任何递归调用中,不同顺序的数字正在(或应该)累积

提前谢谢

import qualified Data.Map as M

g :: Int -> Int -> Int -> Int -> (M.Map Int Bool, Int) -> [Int] -> [[Int]]
g n m digitCount lastDigit (hash,hashCount) digits
  | digitCount == m = if test then [reverse digits] else []
  | otherwise       =
      if lastDigit == 0
         then g n m (digitCount + 1) (lastDigit + 1) (hash',hashCount') (lastDigit:digits)
         else if lastDigit == n - 1
                 then g n m (digitCount + 1) (lastDigit - 1) (hash',hashCount') (lastDigit:digits)
                 else g n m (digitCount + 1) (lastDigit + 1) (hash',hashCount') (lastDigit:digits)
                   ++ g n m (digitCount + 1) (lastDigit - 1) (hash',hashCount') (lastDigit:digits)
 where test = hashCount == n
       (hash',hashCount') = 
         if test
            then (M.empty,hashCount)
            else case M.lookup lastDigit hash of
                   Just anyting -> (hash,hashCount)
                   Nothing      -> (M.insert lastDigit True hash,hashCount + 1)

在最后一个else分支中,对
g
的两个递归调用与
(++)
结合使用时,除了
lastDigit
之外,传递的参数完全相同

递归的基本情况不是查看
lastDigit
——它只是比较
m
digitCount
n
hashCount
,然后返回
[反向数字]

因此,在任何情况下,
(++)
大小写被立即命中,然后基本大小写返回
[反向数字]
,您将得到相同的重复值


我没有完全理解您的问题说明,但在进行递归调用时,您可能需要将
lastDigit
的“新”值添加到digits中,即
(lastDigit-1):digits
(lastDigits+1):digits
在对
g
的两次递归调用中与
(++)结合使用
在最后一个else分支中,除了
lastDigit
之外,您传递的参数完全相同

递归的基本情况不是查看
lastDigit
——它只是比较
m
digitCount
n
hashCount
,然后返回
[反向数字]

因此,在任何情况下,
(++)
大小写被立即命中,然后基本大小写返回
[反向数字]
,您将得到相同的重复值

我没有完全理解您的问题说明,但在进行递归调用时,您可能需要将
lastDigit
的“新”值添加到digits,即
(lastDigit-1):digits
(lastDigit+1):digits

为什么在使用++运算符两次调用g时,我得到的是两个[2,1,0,1],而不是一个[2,1,0,1] 一在我看来,g中的每个结果都应该是不同的,因为在任何递归调用中 不同的数字顺序正在(或应该)累积

但是两个调用中的(Map,Int)对是相同的,因此递归调用不知道另一个调用找到了什么。考虑调用G…(最后一位数字-1)。它也会叫g。。。(lastDigit)(通过将1添加到它得到的(lastDigit-1)中),并遵循分支g。。。(lastDigit+1)生成相同的结果

另外,(Map a())是(Set a),因为不使用Map中的Bool值,所以它与()相同:

导入符合条件的数据。设置为S
g::Int->Int->Int->Int->(S.Set Int,Int)->[Int]->[[Int]]
g n m digitCount lastDigit(哈希、哈希计数)位数
|digitCount==m=如果测试,那么[reverse digits]else[]
|lastDigit<0 | | lastDigit==n=[]
|否则=g n m d'(最后一位数+1)h'(最后一位数:位数)
++g n m d'(最后一位数-1)h'(最后一位数:位数)
其中test=hashCount==n
d'=数字计数+1
h'
|test=(S.empty,hashCount)
|S.member lastDigit哈希=(哈希,哈希计数)
|否则=(S.insert lastDigit散列,hashCount+1)
为什么在使用++运算符两次调用g时,我得到的是两个[2,1,0,1],而不是一个[2,1,0,1] 一在我看来,g中的每个结果都应该是不同的,因为在任何递归调用中 不同的数字顺序正在(或应该)累积

但是两个调用中的(Map,Int)对是相同的,因此递归调用不知道另一个调用找到了什么。考虑调用G…(最后一位数字-1)。它也会叫g。。。(lastDigit)(通过将1添加到它得到的(lastDigit-1)中),并遵循分支g。。。(lastDigit+1)生成相同的结果

另外,(Map a())是(Set a),因为不使用Map中的Bool值,所以它与()相同:

导入符合条件的数据。设置为S
g::Int->Int->Int->Int->(S.Set Int,Int)->[Int]->[[Int]]
g n m digitCount lastDigit(哈希、哈希计数)位数
|digitCount==m=如果测试,那么[reverse digits]else[]
|lastDigit<0 | | lastDigit==n=[]
|否则=g n m d'(最后一位数+1)h'(最后一位数:位数)
++g n m d'(最后一位数-1)h'(最后一位数:位数)
其中test=hashCount==n
d'=数字计数+1
h'
|test=(S.empty,hashCount)
|S.member lastDigit哈希=(哈希,哈希计数)
|否则=(S.insert lastDigit散列,hashCount+1)

现在您已经可以使用它了,这里有一个更通用的方法

我们需要走解决方案之树

    data S a = Solution a | Explore [S a]
解决方案是这棵树的叶子,探索是要探索的选项列表

    -- this is very much unfoldr-like
    generator :: [S a] -> [a]
    generator [] = []
    generator (Solution a: ss) = a: generator ss
    generator (Explore ps: ss) = generator $ ss ++ ps
    main = print $ map reverse $ generator $ g 3 6
现在,给出一个“可能的解决方案”列表,生成一个解决方案列表。生成器模式匹配Explores,并将要探索的解决方案列表附加到列表的末尾。这样我们就在探索
    g :: Int -> Int -> [S [Int]]
    g n m = [Explore $ g' [i] (S.singleton i) | i <- [1..n-1]]  where
      g' is@(h:_) ms
       | h < 0 || h >= n || length is > m = [] --no solution, nothing to explore
       | otherwise = maybeSolution ++ 
                             [ Explore $ g' ((h-1):is) $ S.insert (h-1) ms
                             , Explore $ g' ((h+1):is) $ S.insert (h+1) ms ] 
        where
          maybeSolution
            | S.size ms == n = [Solution is]
            | otherwise      = []
    main = print $ map reverse $ generator $ g 3 6