模式匹配Haskell中IO Monad中的元组

时间:2009-12-28 19:07:19

标签: haskell pattern-matching tuples

我在业余时间一直在研究Haskell,最近进入了monadic功能领域。我已经从我正在研究这个非常人为的例子的练习中提炼出代码,以找出我遇到的确切问题:

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)这样的东西来从元组中提取单个项目,只需分配一个值,但这显然是一种草率和迂回的方式来处理事情。我觉得我可能会磕磕绊绊地看着面对我的语法的一些细微差别。如何解决此类型错误?应该可以直接匹配包含在monad中的元组,不应该吗?

4 个答案:

答案 0 :(得分:2)

我不知道为什么你没有

rndPermu xs = hurf xs

但要回答你问的问题,试试这个

rndPermu xs = do (front, back) <- hurf xs
                 return (front, back)

我的理解是你无法直接匹配IO内的某些内容。您必须先使用<-语法提取它。

答案 1 :(得分:2)

如果我正确理解您要执行的操作,rndPermu会尝试获取IO返回的hurf中的值,并从中移除IO,例如{ {1}}。这是不可能的。 rndPermu :: IO a -> a monad中的返回值表示IO函数使用IO,所有使用hurf调用结果的函数都会间接使用IO:它们的返回值也应该在hurf monad。这是由类型系统强制执行的。

如果你只想在monad中使用模式匹配,最直接的方法是使用do-notation:

IO

一种常见的模式是使用不同的纯函数来进一步处理值。 这些函数只是从rndPermu :: [a] -> IO (a, [a]) rndPermu xs = do (front, back) <- hurf xs return (front, back) 或不同的monad调用,但他们不需要知道:

IO

答案 2 :(得分:1)

作为do块的替代方法,您可以在绑定monadic值的函数中进行模式匹配:

rndPermu xs = hurf xs >>= \(front, back) -> return (front, back)

rndPermu xs = hurf xs >>= \res -> case res of (front, back) -> return (front, back)

答案 3 :(得分:0)

要回答评论中的问题,GHCi 推断rndPermu应该有IO类型。那不是问题。问题是这一行:

 where (front, back) = hurf xs

类型推断只是(松散地)意味着您不必指定要处理的表达式的类型。类型推断并不意味着Haskell只是默默地将一种类型的值转换为另一种类型的值;事实恰恰相反。正如其他人提到的,如果你不想写,你不必编写do块,但你必须处理你有IO值的事实。