无法将 do 内的“IO”类型与“[]”匹配

问题描述 投票:0回答:1

这里是 Haskell 新手 :) 。我不想从 IO 中迭代读取元素,并且如果存在,则从 list 中删除该元素。否则,重复读取,直到输入的元素出现在列表中。我有以下代码:

import Data.List (delete)

main = do
let initialDieRoll = [23,45,98,34]
strength <- askStrength
let dieRollWithoutStrength = removeStrengthFromDieRollLoop strength initialDieRoll
print dieRollWithoutStrength

removeStrengthFromDieRollLoop :: Int -> [Int] -> [Int]
removeStrengthFromDieRollLoop = removeStrengthFromDieRoll

removeStrengthFromDieRoll :: Int -> [Int] -> [Int]
removeStrengthFromDieRoll strength dieRoll = do
if strength `elem` dieRoll then
  delete strength dieRoll
else do
  "Please, choose an element from the initial die roll"
  newStrength <- askStrength
  removeStrengthFromDieRollLoop askStrength dieRoll


askStrength :: IO Int
askStrength = do
putStr "Strength : "
readLn::IO Int

但是,当我请求新的强度时,我收到以下错误:

Couldn't match type ‘IO’ with ‘[]’
  Expected: [Int]
  Actual: IO Int
In a stmt of a 'do' block: newStrength <- askStrength
In the expression:
do "Please, choose an element from the initial die roll"
   newStrength <- askStrength
   removeStrengthFromDieRollLoop askStrength dieRoll
In a stmt of a 'do' block:
  if strength `elem` dieRoll then
    delete st

最好的方法是什么?如何修复该错误,如果该值不在初始列表内,则每次请求循环值的最佳方法是什么? 。谢谢。

loops haskell io
1个回答
0
投票

这是一些可以编译的代码。 (不过我还没运行过)

removeStrengthFromDieRoll :: Int -> [Int] -> IO [Int]
removeStrengthFromDieRoll strength dieRoll = do
  if strength `elem` dieRoll then
    return (delete strength dieRoll)
  else do
    putStrLn "Please, choose an element from the initial die roll"
    newStrength <- askStrength
    removeStrengthFromDieRoll newStrength dieRoll


askStrength :: IO Int
askStrength = do
   putStr "Strength : "
   -- You might need hFlush stdio here, I'm not sure now.
   readLn :: IO Int

一些关键方面:

  • 所有直接或间接执行 IO 的函数,必须具有

    ... -> IO something
    形式的类型。因此,
    askStrength
    必须具有 IO 类型,因为它调用
    putStr
    。因此,
    removeStrengthFromDieRoll
    也必须具有 IO 类型。因此,如果您在另一个函数中使用
    removeStrengthFromDieRoll
    ,它仍然必须具有 IO 类型等。“IO 是病毒式的”是一种常见的表述方式。

  • 如果你需要打印字符串,你需要类似

    putStrLn
    的东西。您不能简单地使用字符串
    "Please, ...."

  • 当您需要返回内部IO,但只有一个非IO值时,如上面的列表

    delete strength dieRoll
    ,您需要使用
    return
    函数(或等效的
    pure
    )将其带入IO内部。请注意,
    return
    与C、C++、Java等中的不同,但在Haskell中仅用于将
    someType
    转换为
    IO someType
    ,以便可以在具有
    IO
    结果类型。

最后,IO 对于初学者来说一开始可能会很难掌握。我们都去过那里。如果您还没有这样做,我建议您遵循 IO monad 教程:网络上应该有很多这样的教程。

© www.soinside.com 2019 - 2024. All rights reserved.