haskell阅读和迭代

时间:2018-04-20 08:10:00

标签: loops haskell

我需要你的帮助。 我试图在haskell学习并做一个简单的任务,但对我来说仍然很难。 我想要做的是:读取用空格分隔的一行数字,迭代该列表,检查值,如果值不为零,则加1,否则为-1。我试着看一些教程和其他项目代码,但它只输出一堆错误。 我的代码:

import System.Environment
import Control.Monad
import Text.Printf
import Data.List
import System.IO

solve :: IO ()
solve = do
    nums <- map read . words <$> getLine
    print (calculate nums)

calculate (x:xs) = x + check xs

check num
    | num == 0 =
        -1
    | otherwise = 
        1

main :: IO ()
main = do
    n <- readLn
    if n /= 0
        then do 
            printf "Case: "
            solve
        else main

错误:

C:\Users\Donatas\Documents\haskell\la3.hs:9:21: error:
    * Ambiguous type variable `b0' arising from a use of `read'
      prevents the constraint `(Read b0)' from being solved.
      Probable fix: use a type annotation to specify what `b0' should be.
      These potential instances exist:
        instance Read BufferMode -- Defined in `GHC.IO.Handle.Types'
        instance Read Newline -- Defined in `GHC.IO.Handle.Types'
        instance Read NewlineMode -- Defined in `GHC.IO.Handle.Types'
        ...plus 25 others
        ...plus six instances involving out-of-scope types
        (use -fprint-potential-instances to see them all)
    * In the first argument of `map', namely `read'
      In the first argument of `(.)', namely `map read'
      In the first argument of `(<$>)', namely `map read . words'
  |
9 |         nums <- map read . words <$> getLine
  |                     ^^^^

C:\Users\Donatas\Documents\haskell\la3.hs:10:9: error:
    * Ambiguous type variable `a0' arising from a use of `print'
      prevents the constraint `(Show a0)' from being solved.
      Probable fix: use a type annotation to specify what `a0' should be.
      These potential instances exist:
        instance Show HandlePosn -- Defined in `GHC.IO.Handle'
        instance Show BufferMode -- Defined in `GHC.IO.Handle.Types'
        instance Show Handle -- Defined in `GHC.IO.Handle.Types'
        ...plus 27 others
        ...plus 13 instances involving out-of-scope types
        (use -fprint-potential-instances to see them all)
    * In a stmt of a 'do' block: print (calculate nums)
      In the expression:
        do nums <- map read . words <$> getLine
           print (calculate nums)
      In an equation for `solve':
          solve
            = do nums <- map read . words <$> getLine
                 print (calculate nums)
   |
10 |         print (calculate nums)
   |         ^^^^^^^^^^^^^^^^^^^^^^

C:\Users\Donatas\Documents\haskell\la3.hs:12:1: error:
    * Non type-variable argument in the constraint: Num [a]
      (Use FlexibleContexts to permit this)
    * When checking the inferred type
        calculate :: forall a. (Eq a, Num [a], Num a) => [a] -> a
   |
12 | calculate (x:xs) = x + check xs
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Failed, no modules loaded.

2 个答案:

答案 0 :(得分:5)

首先,我建议你默认总是写类型注释。在开始实现任何内容之前,请勾勒出程序的类型。对于这个程序,我建议你从:

开始
IO _

这些名字也可能会得到改善,以更好地传达他们正在做的事情。

请注意,只有一个类型为calculate的函数。这可以隔离程序中不纯净的部分,这将使您的生活更轻松(例如测试,代码推理等)。

你离我不远。只需尝试重新编写代码以适应上述类型。请注意,您在const { exec } = require('child_process'); module.exports = function (options, cb) { // turn the options to node-sass cli args // something like this... exec(`node-sass ${agrs}`, execOptions, cb); } 实施中错过了一种模式;)

答案 1 :(得分:0)

如果您检查代码并按照类型进行操作,则错误的位置非常清晰。是的,您可以添加类型注释 - 强烈推荐 - 但我发现您的代码非常简单,您可以通过一些等式推理来解决。

solve开头,很容易看出nums的类型为Read a => [a],因为您按字词分割字符串(即[String])并映射read过了它。因此,a的列表就是您向calculate提供的内容。如您所知,列表是(1)空列表([])和(2)由头部构成的cons单元格,类型为a的元素和尾部之间的不相交和,列表的其余部分((x:xs))。

您首先注意到的是缺少空列表的情况;让我们添加它:

calculate [] = 0 -- I assume this is correct

指向calculatecheck的正文。后者显然期望一个数字,顺便说一下你可以更简洁:

check 0 = -1
check _ = 1

现在,如果您查看calculate,就会看到您正在调用check并将其传递给xs。什么是xs?它以(x:xs)模式绑定,这就是你如何解构cons细胞。显然,xs是单元格的尾部,因此列表本身。但是check期待一个数字!您可以在此处获得的唯一数字是x,而不是xs。因此,让我们将您的代码更改为

calculate (x:xs) = check x + ...

您的规范声明您要迭代列表。只有在使用xs执行某些操作时才会发生这种情况。你能用它做什么?唯一的答案是递归调用calculate

calculate (x:xs) = check x + calculate xs

...通过这些更改,您的代码就可以了。