如何在洗牌列表中打印第一个值?

时间:2018-03-07 22:18:12

标签: haskell

我试图学习惯用的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的上下文中工作,所以我不能在我的其他一个函数中洗一个列表。我不确定是否有更好的方式。

1 个答案:

答案 0 :(得分:1)

试试这个。

toss :: IO ()
toss = do
    shuffled <- shuffleM getTosses
    putStrLn $ "Biff tossed" ++ head shuffled

主要问题是shuffleM的类型为MonadRandom m => [a] -> m [a]。如您所见,mMonadRandom。您不能将包装的值作为 monad 直接传递给纯函数,例如head,因为head具有[a] -> a类型。我们需要解开 MonadRandom。解决此问题的方法之一是使用<-关键字。