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
不使用+;Haskell中的操作员_Haskell_Addition - Fatal编程技术网

不使用+;Haskell中的操作员

不使用+;Haskell中的操作员,haskell,addition,Haskell,Addition,我想将两个正数相加,而不使用任何基本运算符,如+进行加法。我已经解决了这个问题(在add“”函数中)(我认为)可能效率不高,但这不是现在的重点。我得到了很多类型错误,但我不知道如何处理,这对我来说是非常混乱的,因为它在纸上工作,我来自python 加上12457489 --add :: Int -> Int -> Int add x y = add'' (zip (add' x) (add' y)) where add' :: Int -> [Int] add' 0 =

我想将两个正数相加,而不使用任何基本运算符,如+进行加法。我已经解决了这个问题(在add“”函数中)(我认为)可能效率不高,但这不是现在的重点。我得到了很多类型错误,但我不知道如何处理,这对我来说是非常混乱的,因为它在纸上工作,我来自python

加上12457489

--add :: Int -> Int -> Int
add x y = add'' (zip (add' x) (add' y))
 where
 add' :: Int -> [Int]
 add' 0 = []
 add' x = add' (x `div` 10) ++ [x `mod` 10]
转换[1,2,4,5][7,4,8,9],然后将它们压缩在一起[(1,7),(2,4)…]

总结[8,6,…]当总和达到10时发生的情况尚未实施

  where
  --add''' :: (Int,Int) -> Int
  add''' x y = last (take (succ y) $ iterate succ x)
将两个数字相加

  • 不能对元组使用
    head
    last
    。。。坦率地说,您根本不应该使用这些函数,因为它们是不安全的(部分),但它们可以在列表中使用。在Haskell中,列表与元组完全不同。
    要获取元组的元素,请使用模式匹配

    (要获得列表中的元素,模式匹配通常也是最好的。)或者,您可以使用
    fst
    snd
    ,这两种方法在2元组上执行您显然认为
    head
    last
    的操作

  • 明确哪些函数是curry函数,哪些不是。按照编写
    添加''
    的方式,它的类型签名实际上是
    Int->Int->Int
    。这相当于
    (Int,Int)->Int
    ,但它仍然与类型检查器不同

  • add'
    的结果是
    [Int]
    ,但您试图在
    add
    的结果中将其用作
    Int
    。那不行,你需要再次把数字转换成数字

  • 添加“”
    不处理空案例。这很容易修复,但比递归更好的是使用标准的组合符。在您的情况下,这只应在元素方面工作,因此您可以简单地使用
    map
    ——或者在压缩中使用
    zipWith
    。然后,您也不需要打开任何元组,因为它与curried函数一起工作


  • 您尝试的干净版本:

    add :: Int -> Int -> Int
    add x y = fromDigits 0 $ zipWith addDigits (toDigits x []) (toDigits y [])
     where
           fromDigits :: Int -> [Int] -> Int
           fromDigits acc [] = acc
           fromDigits acc (d:ds)
                = acc `seq`  -- strict accumulator, to avoid thunking.
                    fromDigits (acc*10 + d) ds
    
           toDigits :: Int -> [Int] -> [Int]                -- yield difference-list,
           toDigits 0 = id                                  -- because we're consing
           toDigits x = toDigits (x`div`10) . ((x`mod`10):) -- left-associatively.
    
           addDigits :: Int -> Int -> Int
           addDigits x y = last $ take (succ x) $ iterate succ y
    
    请注意,
    zipWith
    要求两个数字的位数相同(正如
    zip

    另外,是的,我在
    fromDigits
    中使用了
    +
    ,这使得整个事情变得毫无意义。实际上,你当然会使用二进制,然后它只是一个按位or,乘法是一个左移位。实际上,您不需要在这里特别注意10溢出,但这只是因为在
    fromdights
    中使用
    +
    的欺骗

  • 不能对元组使用
    head
    last
    。。。坦率地说,您根本不应该使用这些函数,因为它们是不安全的(部分),但它们可以在列表中使用。在Haskell中,列表与元组完全不同。
    要获取元组的元素,请使用模式匹配

    (要获得列表中的元素,模式匹配通常也是最好的。)或者,您可以使用
    fst
    snd
    ,这两种方法在2元组上执行您显然认为
    head
    last
    的操作

  • 明确哪些函数是curry函数,哪些不是。按照编写
    添加''
    的方式,它的类型签名实际上是
    Int->Int->Int
    。这相当于
    (Int,Int)->Int
    ,但它仍然与类型检查器不同

  • add'
    的结果是
    [Int]
    ,但您试图在
    add
    的结果中将其用作
    Int
    。那不行,你需要再次把数字转换成数字

  • 添加“”
    不处理空案例。这很容易修复,但比递归更好的是使用标准的组合符。在您的情况下,这只应在元素方面工作,因此您可以简单地使用
    map
    ——或者在压缩中使用
    zipWith
    。然后,您也不需要打开任何元组,因为它与curried函数一起工作


  • 您尝试的干净版本:

    add :: Int -> Int -> Int
    add x y = fromDigits 0 $ zipWith addDigits (toDigits x []) (toDigits y [])
     where
           fromDigits :: Int -> [Int] -> Int
           fromDigits acc [] = acc
           fromDigits acc (d:ds)
                = acc `seq`  -- strict accumulator, to avoid thunking.
                    fromDigits (acc*10 + d) ds
    
           toDigits :: Int -> [Int] -> [Int]                -- yield difference-list,
           toDigits 0 = id                                  -- because we're consing
           toDigits x = toDigits (x`div`10) . ((x`mod`10):) -- left-associatively.
    
           addDigits :: Int -> Int -> Int
           addDigits x y = last $ take (succ x) $ iterate succ y
    
    请注意,
    zipWith
    要求两个数字的位数相同(正如
    zip


    另外,是的,我在
    fromDigits
    中使用了
    +
    ,这使得整个事情变得毫无意义。实际上,你当然会使用二进制,然后它只是一个按位or,乘法是一个左移位。实际上,您不需要在这里特别注意10溢出,但这只是因为在
    fromDigits

    中使用
    +
    的欺骗,
    head
    last
    您的意思是
    fst
    snd
    ,但您根本不需要它们,组件就在那里:

    add'' :: [(Int, Int)] -> [Int]
    add'' (pair : pairs) = [(add''' pair)] ++ add'' pairs 
      where
      add''' :: (Int, Int) -> Int
      add''' (x, y) = last (take (succ y) $ iterate succ x)
                    = iterate succ x !! y
                    = [x ..] !! y          -- nice idea for an exercise!
    
    现在仍然存在的一个大问题是如何处理这些可怕的10以上数字。这里有一个想法:生成一个数字和一个进位

       = ([(d, 0) | d <- [x .. 9]] ++ [(d, 1) | d <- [0 ..]]) !! y
    

    =([(d,0)| dBy
    head
    last
    您的意思是
    fst
    snd
    ,但您根本不需要它们,组件就在那里:

    add'' :: [(Int, Int)] -> [Int]
    add'' (pair : pairs) = [(add''' pair)] ++ add'' pairs 
      where
      add''' :: (Int, Int) -> Int
      add''' (x, y) = last (take (succ y) $ iterate succ x)
                    = iterate succ x !! y
                    = [x ..] !! y          -- nice idea for an exercise!
    
    现在剩下的一个大问题是如何处理那些可怕的10以上的大数字。这里有一个想法:生成一个数字和一个带进位的数字

       = ([(d, 0) | d <- [x .. 9]] ++ [(d, 1) | d <- [0 ..]]) !! y
    

    =([(d,0)| d其他答案涵盖了您的方法中出现的错误。但是,从理论角度来看,它们都有一些缺点:它们要么将您置于
    [Int]
    而不是
    Int
    ,要么在从
    [Int]返回的转换过程中使用
    (+)
    Int
    。此外,它们使用
    mod
    div
    作为定义加法的子例程——这是可以的,但从理论上讲,您需要确保
    add 0 y = y
    add x y
     | x>0 = add (pred x) (succ y)
     | otherwise = add (succ x) (pred y)