我在业余时间一直在研究 Haskell,最近涉足单子函数领域。我已经将我一直在做的练习中的代码提取到这个非常人为的示例中,以隔离我遇到的确切问题:
import System.Random
rndPermu :: [a] -> IO (a, [a])
rndPermu xs = (front, back)
where (front, back) = hurf xs
hurf :: [a] -> IO (a, [a])
hurf xs = randomRIO (0, (length xs) - 1) >>= \r -> return $ removeAt r xs
removeAt :: Int -> [a] -> (a, [a])
removeAt n xs = (e, rest)
where e = xs !! n
rest = take n xs ++ (tail $ drop n xs)
rndPermu 在加载到 GHCi 时会产生类型错误,说明在“where”子句中需要类型 (t, t1) 但收到了 IO (a, [a])。我可以使用 (liftM fst) 之类的东西从元组中提取单个项目并只分配一个值,但这显然是一种草率而迂回的处理方式。我觉得我可能会因为一些细微的语法细微差别而绊倒在我脸上。如何解决这种类型的错误?应该可以直接匹配一个包裹在单子中的元组,不是吗?