我试图学习惯用的Haskell方式来重新排列列表并从头开始取第一个值。我甚至不确定在我的计划中我应该这样做。到目前为止,我已将逻辑移至此处:
-- {-# LANGUAGE UnicodeSyntax #-}
module RPS
( toss
) where
import System.Random.Shuffle
import Data.List
toss :: IO ()
toss =
-- This doesn't actually work
-- but I'd like to shuffle the list returned by
-- getTosses and pull the first element out
putStrLn "Biff tossed" ++ head shuffleM getTosses
getScissors :: [String]
getScissors =
scissors where scissors = replicate 10 "✂️"
getPaper :: [String]
getPaper =
paper where paper = replicate 10 ""
getRocks :: [String]
getRocks =
rocks where rocks = replicate 10 ""
getPossibilities :: [String] -> [String] -> [String] -> [String]
getPossibilities rocks paper scissors =
rocks ++ paper ++ scissors
getTosses :: [String]
getTosses =
getPossibilities getRocks getPaper getScissors
在GHCi中运行此模块时,我得到了
src/RPS.hs:11:36: error:
• Couldn't match expected type ‘[[String] -> [a1]]’
with actual type ‘[a0] -> m0 [a0]’
• Probable cause: ‘shuffleM’ is applied to too few arguments
In the first argument of ‘head’, namely ‘shuffleM’
In the second argument of ‘(++)’, namely ‘head shuffleM getTosses’
In the expression:
奇怪的是,我可以在GHCi中运行shuffleM getTosses
就好......只有当我尝试在源文件中实际执行此操作然后加载它时,才会失败。我已经读过,shuffle monad只能在IO的上下文中工作,所以我不能在我的其他一个函数中洗一个列表。我不确定是否有更好的方式。
答案 0 :(得分:1)
试试这个。
toss :: IO ()
toss = do
shuffled <- shuffleM getTosses
putStrLn $ "Biff tossed" ++ head shuffled
主要问题是shuffleM
的类型为MonadRandom m => [a] -> m [a]
。如您所见,m
是MonadRandom
。您不能将包装的值作为 monad 直接传递给纯函数,例如head
,因为head
具有[a] -> a
类型。我们需要解开 MonadRandom
。解决此问题的方法之一是使用<-
关键字。