1

你好这里是我的问题。这是我的运行代码,很好:

showBalls = do
      howMany <- getInt
      return . take HowMany $ repeat 9

我的 getInt 进行了几次检查以检索用户输入 Int。但是,我的问题是,有没有办法使用 monad 重写这部分代码?

我的目标是使用 >>= 并具有最终的单行功能,例如:

showBalls = fmap (take <$> (repeat 9)) getLine

但是它不起作用(如预期的那样)。有什么建议吗?

4

3 回答 3

2

您可以使用flip来反转 的参数take,这使得可以应用repeat 9到它并获取函数:

> :t flip take (repeat 9)
flip take (repeat 9) :: Num a => Int -> [a]

要与我们一起使用>>=getInt我们需要Int -> IO a功能:

> :t (getInt >>=)
(getInt >>=) :: (Int -> IO b) -> IO b

要做到这一点,请组合使用return(这是m [a]因为它适用于每个 monad,但也仅限于列表;从上述类型,m成为IOb成为[a]):

> :t return . flip take (repeat 9)
return . flip take (repeat 9) :: (Monad m, Num a) => Int -> m [a]

最后的表达式是:

> :t getInt >>= return . flip take (repeat 9)
getInt >>= return . flip take (repeat 9) :: Num a => IO [a]

但是,正如我所提到的,我并不真的相信它比原版更好。作为一种更有用的知识,在 GHCi 中使用表达式及其类型是发明此类转换的好方法。

于 2013-01-09T18:18:19.230 回答
2

我自己也得到了它,但使用 lambda 表示法:)

showBalls = getInt >>= (\a -> return . take a $ repeat 9 )
于 2013-01-09T18:18:48.687 回答
1

我相信这应该有效:

showBalls = (liftM . flip take $ repeat 9) getInt

可能也有无积分的方法,但我无法弄清楚。

于 2013-01-09T18:16:44.657 回答