从整数

时间:2018-01-10 21:32:51

标签: haskell

这是我遇到的一个家庭作业问题:

  

输入一个大于或等于0的整数。将它乘以5,将6加到乘积上,乘以4,加9并乘以5.然后,删除最后一个数的最后两位数并减去1输出答案。

这是我的代码:

1  main = do
2      putStrLn "enter a non-negative integer: "
3      input <- getLine
4      let i = (read input :: Int)
5      print ((((i * 5) + 6) * 4 + 9) * 5)/100-1

在这里,我试图将最后两位数除以100,因为这适用于其他语言。 但是,它给了我这个错误,我不确定它的含义:

$ runhaskell Computations.hs

Computations.hs:5:5: error:
    • No instance for (Fractional (IO ())) arising from a use of ‘/’
    • In the first argument of ‘(-)’, namely
        ‘print ((((x * 5) + 6) * 4 + 9) * 5) / 100’
      In a stmt of a 'do' block:
        print ((((x * 5) + 6) * 4 + 9) * 5) / 100 - 1
      In the expression:
        do { putStrLn "enter a non-negative integer: ";
             input1 <- getLine;
             let x = (read input1 :: Int);
             print ((((x * 5) + 6) * 4 + 9) * 5) / 100 - 1 }

Computations.hs:5:5: error:
    • No instance for (Num (IO ())) arising from a use of ‘-’
    • In a stmt of a 'do' block:
        print ((((x * 5) + 6) * 4 + 9) * 5) / 100 - 1
      In the expression:
        do { putStrLn "enter a non-negative integer: ";
             input1 <- getLine;
             let x = (read input1 :: Int);
             print ((((x * 5) + 6) * 4 + 9) * 5) / 100 - 1 }
      In an equation for ‘main’:
          main
            = do { putStrLn "enter a non-negative integer: ";
                   input1 <- getLine;
                   let x = ...;
                   .... }

那么,任何人都可以解释错误的含义吗?

还有其他解决办法比除数除外更好吗?

如何删除任意位置的数字?例如,从整数中删除第一个,第二个和第六个数字?

ps:如果正确完成,输入和输出应匹配。

更新:我已将“/”改为“div”,它给了我这个:

Computations.hs:5:12: error:
    • Couldn't match expected type ‘(Integer -> Integer -> Integer)
                                    -> Integer -> Integer’
                  with actual type ‘Int’
    • The function ‘(((i * 5) + 6) * 4 + 9) * 5’
      is applied to two arguments,
      but its type ‘Int’ has none
      In the first argument of ‘(-)’, namely
        ‘((((i * 5) + 6) * 4 + 9) * 5) div 100’
      In the first argument of ‘print’, namely
        ‘(((((i * 5) + 6) * 4 + 9) * 5) div 100 - 1)’

这部分很奇怪:“函数'(((i * 5)+ 6)* 4 + 9)* 5'应用于两个参数”,为什么haskell将其解释为函数?

2 个答案:

答案 0 :(得分:3)

删除任意位置的数字是一个有趣的问题。这可能是最简单的方法,转换为字符串并执行字符串操作,然后作为Int读回。由于Int同时实现ShowRead,您可以执行以下操作:

type Digit = Int

removeDigits :: [Digit] -> Int -> Int
removeDigits digits = read . go 1 . show
  where
  go _ []     = []
  go i (c:cs) | i `elem` digits = go cs (i+1)
              | otherwise       = c : go cs (i+1)
-- N.B. I chose 1-indexing here instead of 0-indexing because of your word choice
-- "remove the first, second, and sixth digits" maps naturally to [1, 2, 6],
-- though programmers may find that off-putting. YMMV.

removeDigits这里可以重写为

read [c | (i, c) <- zip [1..] (show n), i `notElem` digits]

答案 1 :(得分:3)

任何人都可以解释错误的含义吗?

第一行中的优先级为off - 中缀函数(如/)通常具有比普通函数更高的优先级,因此print (...) / 100等同于(print ...) / 100,这显然是有问题的。您可以将所有内容括在括号中,或使用$函数:

print $ ((((i * 5) + 6) * 4 + 9) * 5) / 100 - 1

现在,由于您已将i限制为Int,因此仍会出现错误:/仅针对Fractional类型类的实例定义,并且Int不是。您需要整数除法divquot,它仅在Integral上运行(其中Int是一个实例),并根据需要执行截断:

print $ ((((i * 5) + 6) * 4 + 9) * 5) `div` 100 - 1

注意反引号(`),它允许使用正常函数作为中缀。你可以写成:

print $ (div ((((i * 5) + 6) * 4 + 9) * 5) 100) - 1

但是后面的括号让事情变得难以阅读。

还有其他解决方案比按除数截断更好吗?

一般情况下可能没有,但是as mentioned on your other question,这个特定的等式总会给你与输入相同的结果,所以你可以写:

main = getLine >>= print

如何删除任意位置的数字?

转换为字符串并删除字符可能是您最好的选择。像下面这样的东西会起作用,虽然它可能有点密集:

removeDigits :: [Int] -> Int -> Int
removeDigits indices x = read . reverse . filterIndices indices . reverse . show $ x

filterIndices :: [Int] -> [a] -> [a]
filterIndices inds elems = map snd . filter ((`notElem` inds) . fst) . zip [1..] $ elems

请注意,这会将最后一位数字视为“第一”数字 - 用数字引用数字会更自然。

(在我看来)更容易阅读现有代码的表示形式是:

transform = (subtract 1) . (`quot` 100) . (*5) . (+9) . (*4) . (+6) . (*5)

通过这种写作方式,组合会覆盖算术优先级法则,让我们把它写成如何阅读(“时间5,加6,时间4,......”)。我们必须使用subtract 1,因为-1被解释为文字值-1,而不是一元函数。