繁体   English   中英

读取IO字符串并在Haskell中返回自定义数据类型列表

[英]Read IO String and return custom data type list in Haskell

我是Haskell的初学者,并且在IO操作方面遇到困难。 我应该从用户那里获取IO String,直到用户发送“。”为止。 (点)字符。 我将使用这些输入来通过解析字符串来转换自定义数据类型,命名卡。 然后将卡添加到列表中。 当用户键入“。”时,我将发送整个卡列表。 Haskell代码如下:

readCards :: IO [Card]
readCards = return (returnCardList [])
    where 
        returnCardList :: [Card] -> [Card]
        returnCardList acc =  do line <- getLine
                                 if line == "."
                                 then acc
                                 else returnCardList ((convertCard (line !! 0) (line !! 1)):acc)

convertCard是一个需要两个char并返回Card的函数。 也是acc代表尾部递归函数的累加器(不必使用尾部递归来实现,我只是选择了它)。

例如returnCardList 'h' 'q'给出Card {suit=Hearts, rank=Queen}

但是上面的代码分区给出了一个错误:

 Couldn't match type `IO' with `[]'
 Expected type: [String]
 Actual type: IO String

但是下面的代码(带有虚拟卡列表)可以正常运行:

readCards :: IO [Card]
readCards = return [Card {suit=Clubs, rank=King}, Card {suit=Clubs, rank=Ace}, Card {suit=Clubs, rank=Jack}]

我读了很多东西,但无法解决。 我真的很想知道我想念什么。

这段代码

readCards :: IO [Card]
readCards = return (returnCardList [])

指出readCards是实际上不做IO的IO计算。 实际上, return something表示未执行任何IO,并且something[Card]类型的纯值。

这不是您想要的。 你需要类似的东西

readCards :: IO [Card]
readCards = returnCardList []

因此,IO必须由returnCardList完成,该类型现在必须具有

returnCardList :: [Card] -> IO [Card]
                         -- ^^ we do perform IO here!

您自己的实现应该可以正常工作

    returnCardList acc = do 
       line <- getLine
       if line == "."
       then return acc
         -- ^^^^^^ turn the plain value into an IO computation
       else returnCardList ((convertCard (line !! 0) (line !! 1)):acc)

可以这样重写:

    returnCardList acc = do 
       line <- getLine
       case line of
          "." -> return acc
          (c1:c2:_) -> returnCardList (convertCard c1 c2 : acc)
          _ -> ... -- you should handle here the other cases (length < 2)

请注意,您也可以不使用acc参数:

    returnCardList = do 
       line <- getLine
       case line of
          "." -> return []
          (c1:c2:_) -> (convertCard c1 c2 :) <$> returnCardList
          _ -> ... -- you should handle here the other cases (length < 2)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM