List Haskell获取IO列表元素

List Haskell获取IO列表元素,list,haskell,io,element,monads,List,Haskell,Io,Element,Monads,我有一张由元组组成的类型同义词卡片。我还有一个类型同义词Deck定义为[Card](卡片列表) 由于文件读取,我一直使用IO monad,具体来说,我有一个IO Deck类型的对象。如何检索卡列表中的各个元素?由于IO monad,类型似乎不再是列表,因此我无法使用!!操作员。假设这些是您的类型: type Card = (Int, Int) type Deck = [Card] someDeck :: IO Deck someDeck = undefined -- Some sample

我有一张由元组组成的类型同义词卡片。我还有一个类型同义词Deck定义为[Card](卡片列表)


由于文件读取,我一直使用IO monad,具体来说,我有一个IO Deck类型的对象。如何检索卡列表中的各个元素?由于IO monad,类型似乎不再是列表,因此我无法使用!!操作员。

假设这些是您的类型:

type Card = (Int, Int)

type Deck = [Card]

someDeck :: IO Deck
someDeck = undefined -- Some sample IO Deck which you have (from reading file etc.)
然后,您可以使用monad do表示法访问
数据组

{-# LANGUAGE ScopedTypeVariables #-}

testFun :: IO Deck
testFun = do
  (x :: Deck) <- someDeck
  -- Operate here on the x value                 
  return []
{-#语言范围的TypeVariables}
testFun::IO甲板
testFun=do

(x::Deck)您应该将用于加载游戏本身的代码从游戏中分离出来,然后在某个地方将两者结合起来。模板可以是:

import System.Environment (getArgs)

solve :: Deck -> Deck
solve deck = -- do something here

loadDeckFromFile :: FilePath -> IO Deck
loadDeckFromFile fp = -- load deck code here

main :: IO ()
main = do
  deckFile <- fmap head getArgs
  deck <- loadDeckFromFile deckFile
  let solvedDeck = solve deck

  putStrLn "Starting deck:"
  print deck
  putStrLn "\nSolved deck:"
  print solvedDeck
导入系统环境(getArgs)
求解::Deck->Deck
解决甲板=--在这里做点什么
loadDeckFromFile::FilePath->IO组
loadDeckFromFile fp=--此处加载甲板代码
main::IO()
main=do

deckFile您的主要问题是您根本不知道如何操作monad,因此这里有一些提示:

单子有一些函数允许对它们进行操作。这些源于monad typeclass中定义的基本类型,
return
>=
(也称为“bind”)

return
允许构造单子,并且
>=
首先获取单子,然后获取构造单子的函数,并将该函数应用于给定的值。这是您在案例中使用它的方式:

-- Imagine your list to be here:
ioList :: IO [Int]
ioList = return [1,2,3,4,5]

-- If we were to print the second element...
main = ioList >>= ( \a -> return (a !! 1) ) >>= print

-- We could write this in do-notation, syntactic sugar for the above:
main = do
    list <- ioList
    print (list !! 1)

你可以找到更多的操作monad的方法,以及对所涉及的各种类型签名的解释,还有donotation和其他方法。

fmap(!!x)ioDeck
-或
ioDeck>=(\deck->使用deck做一些事情)
你可以在这里找到如何操作monad:我认为这有点误导“操纵单子”。单子是一个一劳永逸的东西,一个数学概念,你不能操纵它!你也不能操纵单子值(也称为动作;我想这就是你在这里的意思).像
>=
这样的运算符不操纵,而是组合这些操作。@leftaroundabout这是真的,但在初学者的水平上,用一种更基本的方式来考虑它可能是一个更好的主意,即组合操作。我当然发现用前一种方式思考更容易。你如何将其应用于过滤?我有一个过滤谓词iolist,其中io列表是IO数据组,谓词是Card->Bool。我尝试使用liftM,但不起作用。@wolx如果使用
liftM(筛选器谓词),它应该可以正常工作ioList
-它对我来说就是这样。你的问题可能是你没有像我一样将函数括在括号中。你还需要导入
控件。Monad
,其中
liftM
来自哪里。别担心,我是通过使用fmap来管理的。:)fmap(过滤谓词)ioList编辑:你赢了,再次感谢你!
import Control.Monad
main = print (liftM (!! 1) ioList)