【发布时间】:2018-01-12 20:12:15
【问题描述】:
bind 函数 (>>=) 具有签名:
m a -> (a -> m b) -> m b
但是,我想要一个带有签名的函数:
m (t a) -> (a -> m (t b)) -> m (t b)
具体来说,我有一个给定整数的函数,它返回 IO 中的整数列表:
f :: Int -> IO [Int]
但我想将它应用到 IO of list of Integers 并且我不能使用常规绑定函数,因为它被包装在两个容器中,即包含在 IO 中的列表。 Searching on hoogle 没有帮助。
我正在使用以下方法来实现这一点:
假设函数的实现是:
f :: Int -> IO [Int]
f x = do
return $ [x-10, x+10]
我正在使用两个辅助函数来获得我想要的:
f' :: [Int] -> IO [Int]
f' xs = do
list <- traverse f xs
return $ join list
f'' :: IO [Int] -> IO [Int]
f'' xs = do
ys <- xs
f' ys
以上方法可行,但我想知道是否有更好/惯用的方法在 haskell 中实现它?
【问题讨论】:
-
我不是在寻找解决方案,因为我已经有了。我想要一种惯用的方法来解决这个问题。
-
我不知道您是否已经阅读了答案,但是 "更一般地说,什么函数的类型为 m1 m2 a -> (a -> m1 m2 b) -> m1 m2 b?" 是该重复问题的一部分。答案是:一般情况下是不可能的。见第二个答案。
-
如果您删除
f'和f''上的类型签名并将f抽象为参数,您将获得类型检查器推断出的最通用类型。我想说这些实现是惯用的,除了可能使用do表示法而不是>>=和fmap,但这些纯粹是文体问题。就目前而言,这个问题完全是基于意见的——你能澄清一下你的代码不够好吗,即你希望看到“更好”的版本完成什么?
标签: haskell monads idioms io-monad