Haskell程序修复

时间:2014-05-07 05:19:04

标签: haskell

你可以帮我修复这段代码吗?

import Data.Char
import Data.List

-- 1 2 3 4 5 6 7 8

colors = [1,2,3,4,5]

--game :: [Integer] -> [Char]
game a = do 
      let black = test a color
          white = (test2 a color) - black
      let x = [a] ++ createScore black white
      show x

test [] [] = 0
test (x:xs) (y:ys) = if x == y then 1+test xs ys else 0+test xs ys

test2 a b = length (intersection a b)

intersection first second = [n | n <- first ,  isInfixOf [n] second]

createScore c b = [(take c (repeat 1) ++ take b (repeat 0))]

start = do 
      a <- getLine
      let b = map read $ words a
      --print b
      game b 
      start  

我遇到IO和nonIO功能问题。 该计划的描述:

  1. 从行
  2. 读取数据
  3. 将数据转换为int of int
  4. 调用函数游戏(采用类似参数的列表)
  5. 进行一些计算
  6. 打印分数
  7. 从1
  8. 重新开始

    问题在于功能开始,我不知道如何解决它。

    感谢您的帮助。

2 个答案:

答案 0 :(得分:3)

有些事情与您提供给我们的代码无关。

我将解决编译错误。

首次加载时,我们收到名称错误:

ex1.hs:10:26:
Not in scope: 'color'
Perhaps you meant 'colors' (line 6)

(再次在第11行)

当然编译器是正确的,我们只需要更改相应的名称即可。

接下来,我们假设您在IO和非IO功能方面提到了有趣的一个:

ex1.hs:28:7:
Couldn't match type '[]' with 'IO'
Expected type: IO Char
  Actual type: String
In the return type of a call of 'game'
In a stmt of a 'do' block: game b
In the expression:
  do { a <- getLine;
       let b = map read $ words a;
       game b;
       start }

错误是您在game b阻止中使用IO

您对game的函数定义注释掉的类型注释实际上是正确的 - 它是[Integer] -> [Char]

因此它是一个纯粹的功能,我们不需要使用do符号来描述它,就像我们处理IO的东西一样 - 因为你在这里使用了符号使用列表的参数,do表达式表示列表上下文中的计算,而不是IO计算,因此从start调用它具有类型不匹配,它期望IO ,但它找到了[]

我们可以使用game表达式将let-in转换为纯函数来开始修复它。

game :: [Integer] -> [Char]
game a = let black = test a colors
             white = (test2 a colors) - black
             x = [a] ++ createScore black white
         in show x

所以现在我们有一个函数返回输入的字符串及其得分。

编译器现在提供错误Expected type: IO Char, Actual type: [Char],这是因为我们仍在尝试在主do块中使用非IO表达式。

我们可以通过将字符串实际打印到stdout来解决这个问题,只需使用print,这样你的原始

--print b
game b

可以

print $ game b

此时程序编译!

不幸的是,它仍然不太正确,当我们运行它并输入1 2 3之类的整数列表时,我们得到异常ex1.hs:(14, 1)-(15,66): Non-exhaustive patterns in function test

这个归结为您对test的定义:

test [] [] = 0
test (x:xs) (y:ys)

没有考虑到一个列表为空的可能性 - 因为检查总是在列表的头元素之间进行,可能是解决这个问题的最小修改可能只是:

test (x:xs) (y:ys) = if x == y then 1+test xs ys else 0+test xs ys
test _ _ = 0

现在程序编译并执行。希望这是有道理的。

答案 1 :(得分:0)

game是(或应该是)纯函数,因此您需要使用在start函数中返回IO值的函数来调用它,例如: G。 print $ game b。 也没有理由在那里使用do符号(你可以因为[a]也是monad,但你不能以任何方式利用它)。您可以使用game a = show x并将let语句替换为where块(或使用let ... in)。 test应该能够处理一个列表为空而另一个列表为空的情况,或者您需要确保两个列表的大小始终相同。