我是 Haskell 新手 :)。我想从 IO 中迭代读取一个元素,如果存在,则从列表中删除该元素。在其他情况下,重复读取直到输入的元素在列表中。我有以下代码:
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
最好的处理方法是什么?如何修复错误?如果值不在初始列表中,每次请求值循环的最佳方法是什么?谢谢。
这是一些可以编译的代码。(不过我还没有运行过)
一些关键方面:
所有直接或间接执行 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 教程,如果你还没有这样做的话:网上应该有很多这样的教程。