2014-05-07 91 views
0

你能帮我修复这段代码吗?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. 数据转换为INT
  3. 通话功能的游戏列表(这需要像parametr INT的列表)
  4. 做一些计算
  5. 打印得分
  6. 再次从1开始

问题在功能启动,我不知道如何解决它。

感谢您的帮助。

+0

您应该添加错误消息。 – Nicolas

回答

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 } 

的错误是你在IO块使用game b

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

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

我们可以通过使用let-in表达式将game变成纯函数来开始修复它。

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 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 

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

+0

感谢这个有用的答案,但我仍然得到错误信息'错误 - 无法找到“显示”功能: ***表达式:开始 ***类型:IO a' – Alrick

+0

嘿阿里克 - 首先,看起来像你'使用拥抱,所以很抱歉引用我的ghci错误信息在你身上。你得到的这个错误可能是因为你在代码的某个地方有'show start',hugs不能'show',因为多态类型'IO a'不是'show'类型类的成员。也就是说,你有一个带有未知参数'a'的类型,那么拥抱怎样才能找出要打印的东西呢?对于它的价值,下面是将在我的机器上编译和运行的给定代码的完整文本:https://gist.github.com/kjgorman/8e999820d45dfc2e2884 – kieran

+0

感谢它现在的作品。拥抱有无限递归的问题,我通过if,else语句修复了它 – Alrick

0

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