Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.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
此function中终止递归的惯用Haskell方法_Haskell_Recursion_Functional Programming - Fatal编程技术网

此function中终止递归的惯用Haskell方法

此function中终止递归的惯用Haskell方法,haskell,recursion,functional-programming,Haskell,Recursion,Functional Programming,什么是停止该函数递归的更haskellish的方法?目前我使用嵌套的if/else,如果下一个组合“溢出”,则返回一个空列表 nextcom[][]=[] nextcomb lst最大值|长度lst==长度最大值= 设lastel=last lst 如果lastel[1,1,1,2] [1,1,1,9]->[1,1,2,1] [1,1,9,9]->[1,2,1,1] 等等 但是,第二个参数是一个列表,指示每列的最大值。如果最大值是[2,3],初始列表是[1,1],那么级数应该是: [1,1]

什么是停止该函数递归的更haskellish的方法?目前我使用嵌套的if/else,如果下一个组合“溢出”,则返回一个空列表

nextcom[][]=[]
nextcomb lst最大值|长度lst==长度最大值=
设lastel=last lst
如果lastel
澄清一下,它所做的是取一个类似于[1,1,1,1]的数字列表,并按如下方式递增:

[1,1,1,1]->[1,1,1,2]

[1,1,1,9]->[1,1,2,1]

[1,1,9,9]->[1,2,1,1]

等等

但是,第二个参数是一个列表,指示每列的最大值。如果最大值是[2,3],初始列表是[1,1],那么级数应该是:

[1,1]->[1,2]

[1,2]->[1,3]

[1,3]->[2,1]

[2,1]->[2,2]

[2,2]->[2,3]

[2,3]->[]


编辑:chepner推荐的“Little Endian”版本

nextcomb' [] [] = []
nextcomb' lst maxes | length lst /= length maxes = []
nextcomb' lst maxes =
    let firstel = head lst
    in if    firstel < head maxes
       then (firstel+1) : (tail lst)
       else let higherbit = (nextcomb' (tail lst) (tail maxes))
            in if   higherbit == []
               then []
               else 1 : higherbit
nextcom'[]=[]
nextcomb'lst最大值|长度lst/=长度最大值=[]
nextcomb的lst最大值=
让firstel=头lst
在if firstel
如果您的
表达式只是隐藏了真正的基本情况,即如果任一参数为空,则返回空列表

nextcomb [] [] = []
nextcomb lst maxes | length lst != length maxes = []
nextcomb lst maxes = let lastel = last lst
                     in if    lastel < last maxes
                        then (init lst) ++ [lastel+1]
                        else let higherbit = (nextcomb (init lst) (init maxes)) 
                             in if   higherbit == [] 
                                then []
                                else higherbit ++ [1]

下面是一个使用
报告错误的示例。我不会担保的设计,除了说它的类型检查和运行。它与以前的代码没有太大区别;它只使用
来提升
反向
(0:)
来处理
类型的参数,即字符串[a]
而不是
[a]
类型的参数

import Control.Applicative
nextcombE lst maxes = reverse <$> nextcombE' (reverse lst) (reverse maxes)

nextcombE' [] [] = Right []
nextcombE' [] _ = Left "maxes too long"
nextcombE' _ [] = Left "maxes too short"
nextcombE' (x:xs) (m:ms) | x > m = Left "digit too large"
                         | x < m = Right ((x+1):xs)
                         | otherwise = (0:) <$> (nextcombE' xs ms)
导入控件。应用程序
nextcombE lst最大值=反向nextcombE'(反向lst)(反向最大值)
下一个成员'[]]=右[]
nextcombE'[].=左“最大值太长”
nextcombE'[]=左“最大值太短”
nextcombE'(x:xs)(m:ms)| x>m=左“数字太大”
|x
如果您的
表达式只是隐藏了真正的基本情况,即如果任一参数为空,则返回空列表

nextcomb [] [] = []
nextcomb lst maxes | length lst != length maxes = []
nextcomb lst maxes = let lastel = last lst
                     in if    lastel < last maxes
                        then (init lst) ++ [lastel+1]
                        else let higherbit = (nextcomb (init lst) (init maxes)) 
                             in if   higherbit == [] 
                                then []
                                else higherbit ++ [1]

下面是一个使用
报告错误的示例。我不会担保的设计,除了说它的类型检查和运行。它与以前的代码没有太大区别;它只使用
来提升
反向
(0:)
来处理
类型的参数,即字符串[a]
而不是
[a]
类型的参数

import Control.Applicative
nextcombE lst maxes = reverse <$> nextcombE' (reverse lst) (reverse maxes)

nextcombE' [] [] = Right []
nextcombE' [] _ = Left "maxes too long"
nextcombE' _ [] = Left "maxes too short"
nextcombE' (x:xs) (m:ms) | x > m = Left "digit too large"
                         | x < m = Right ((x+1):xs)
                         | otherwise = (0:) <$> (nextcombE' xs ms)
导入控件。应用程序
nextcombE lst最大值=反向nextcombE'(反向lst)(反向最大值)
下一个成员'[]]=右[]
nextcombE'[].=左“最大值太长”
nextcombE'[]=左“最大值太短”
nextcombE'(x:xs)(m:ms)| x>m=左“数字太大”
|x
请检查下一个实现是否对您有用,因为一种更“haskellish”的方法(至少对我来说)是使用内置递归函数来实现相同的目标

nextcomb [] [] = []
nextcomb lst maxes
  | length lst /= length maxes = []
  | lst == maxes = []
  | otherwise = fst $ foldr f ([],True) $ zip lst maxes
  where
    f (l,m) (acc, mustGrow)
      | mustGrow && l < m  = (l + 1:acc, False)
      | mustGrow = (1:acc, True)
      | otherwise = (l:acc, False)
nextcom[][]=[]
nextcomb lst最大值
|长度lst/=长度最大值=[]
|lst==最大值=[]
|否则=fst$foldr f([],True)$zip lst maxes
哪里
f(l,m)(acc,mustGrow)
|mustGrow&l
(已编辑)如果需要捕获错误,则可以尝试以下操作:

nextcomb [] _ = Left "Initial is empty"
nextcomb _ [] = Left "Maximus size are empty"
nextcomb lst maxes
  | length lst /= length maxes = Left "List must be same length"
  | lst == maxes = Left "Initial already reach the limit given by Maximus"
  | otherwise = Right $ fst $ foldr f ([],True) $ zip lst maxes
  where
    f (l,m) (acc, mustGrow)
      | mustGrow && l < m  = (l + 1:acc, False)
      | mustGrow = (1:acc, True)
      | otherwise = (l:acc, False)
nextcomb[]\uu=Left“初始值为空”
nextcomb[]=左“最大大小为空”
nextcomb lst最大值
|长度lst/=length maxes=Left“列表长度必须相同”
|lst==maxes=Left“初始值已达到Maximus给出的极限”
|否则=右$fst$foldr f([],真)$zip lst maxes
哪里
f(l,m)(acc,mustGrow)
|mustGrow&l
请检查下一个实现是否对您有用,因为一种更“haskellish”的方法(至少对我来说)是使用内置递归函数来实现相同的目标

nextcomb [] [] = []
nextcomb lst maxes
  | length lst /= length maxes = []
  | lst == maxes = []
  | otherwise = fst $ foldr f ([],True) $ zip lst maxes
  where
    f (l,m) (acc, mustGrow)
      | mustGrow && l < m  = (l + 1:acc, False)
      | mustGrow = (1:acc, True)
      | otherwise = (l:acc, False)
nextcom[][]=[]
nextcomb lst最大值
|长度lst/=长度最大值=[]
|lst==最大值=[]
|否则=fst$foldr f([],True)$zip lst maxes
哪里
f(l,m)(acc,mustGrow)
|mustGrow&l
(已编辑)如果需要捕获错误,则可以尝试以下操作:

nextcomb [] _ = Left "Initial is empty"
nextcomb _ [] = Left "Maximus size are empty"
nextcomb lst maxes
  | length lst /= length maxes = Left "List must be same length"
  | lst == maxes = Left "Initial already reach the limit given by Maximus"
  | otherwise = Right $ fst $ foldr f ([],True) $ zip lst maxes
  where
    f (l,m) (acc, mustGrow)
      | mustGrow && l < m  = (l + 1:acc, False)
      | mustGrow = (1:acc, True)
      | otherwise = (l:acc, False)
nextcomb[]\uu=Left“初始值为空”
nextcomb[]=左“最大大小为空”
nextcomb lst最大值
|长度lst/=length maxes=Left“列表长度必须相同”
|lst==maxes=Left“初始值已达到Maximus给出的极限”
|否则=右$fst$foldr f([],真)$zip lst maxes
哪里
f(l,m)(acc,mustGrow)
|mustGrow&l
您应该使非法状态不可表示

因此,与其使用两个列表,不如使用元组列表。例如,每个元组中的第一个值可能是最大值,第二个值可能是实际值


这也大大简化了逻辑,因为“maxes太长”和“maxes太短”错误不会发生。

您应该使非法状态不可表示。

因此,与其使用两个列表,不如使用元组列表。例如,每个元组中的第一个值可以是max
import Control.Monad.State  -- gonna use this a bit later

type Base = Int
type Digit = Int
type Carry = Bool

-- | Increment a single digit, given all the contextual information.
singleDigit' :: Base -> Digit -> Carry -> (Digit, Carry)
singleDigit' base digit carry = (digit', carry')
    where sum = digit + if carry then 1 else 0
          digit' = if sum < base then sum else sum - base
          carry' = base <= sum
-- | Wrap the `singleDigit'` function into the state monad.
singleDigit :: Base -> Digit -> State Carry Digit
singleDigit base digit = state (singleDigit' base digit)
increment :: [Base] -> [Digit] -> [Digit]
increment bases digits = evalState (sequence steps) True
    where steps :: [State Carry Digit]
          steps = zipWith singleDigit bases digits
>>> take 20 (iterate (increment [3,4,5,10]) [0,0,0,0])
[[0,0,0,0],[1,0,0,0],[2,0,0,0]
,[0,1,0,0],[1,1,0,0],[2,1,0,0]
,[0,2,0,0],[1,2,0,0],[2,2,0,0]
,[0,3,0,0],[1,3,0,0],[2,3,0,0]
,[0,0,1,0],[1,0,1,0],[2,0,1,0]
,[0,1,1,0],[1,1,1,0],[2,1,1,0]
,[0,2,1,0],[1,2,1,0]
]