对于monad M
,是否可以将A => M[B]
变为M[A => B]
?
我试过跟踪这些类型无济于事,这让我觉得它不可能,但我想我还是要问。此外,搜索Hoogle a -> m b -> m (a -> b)
并没有返回任何内容,因此我没有太多运气。
答案 0 :(得分:55)
不,这是不可能的,至少不是以有意义的方式。
考虑这个Haskell代码
action :: Int -> IO String
action n = print n >> getLine
首先取n
,打印它(此处执行IO),然后从用户读取一行。
假设我们有一个假设的transform :: (a -> IO b) -> IO (a -> b)
。然后作为心理实验,考虑:
action' :: IO (Int -> String)
action' = transform action
在知道n
之前,上面必须事先做所有IO,然后返回一个纯函数。这不能等同于上面的代码。
要强调这一点,请考虑以下无意义的代码:
test :: IO ()
test = do f <- action'
putStr "enter n"
n <- readLn
putStrLn (f n)
奇怪的是,action'
应事先知道用户下一步要输入的内容!会话看起来像
42 (printed by action')
hello (typed by the user when getLine runs)
enter n
42 (typed by the user when readLn runs)
hello (printed by test)
这需要一台时间机器,因此无法完成。
不,它无法完成。该论点类似于the one I gave to a similar question。
假设存在矛盾transform :: forall m a b. Monad m => (a -> m b) -> m (a -> b)
。
将m
专门化为continuation monad ((_ -> r) -> r)
(我省略了newtype包装器)。
transform :: forall a b r. (a -> (b -> r) -> r) -> ((a -> b) -> r) -> r
专业化r=a
:
transform :: forall a b. (a -> (b -> a) -> a) -> ((a -> b) -> a) -> a
应用:
transform const :: forall a b. ((a -> b) -> a) -> a
通过库里 - 霍华德的同构,以下是直觉主义的同义反复
((A -> B) -> A) -> A
但这是Peirce定律,这在直觉主义逻辑中是不可证明的。矛盾。
答案 1 :(得分:4)
其他回复很好地说明了对于任何monad a -> m b
,通常无法从m (a -> b)
到m
实现函数。但是,有一些特定的monad很可能实现这个功能。一个例子是读者monad:
data Reader r a = R { unR :: r -> a }
commute :: (a -> Reader r b) -> Reader r (a -> b)
commute f = R $ \r a -> unR (f a) r
答案 2 :(得分:3)
没有
例如,Option
是一个monad,但函数(A => Option[B]) => Option[A => B]
没有有意义的实现:
def transform[A, B](a: A => Option[B]): Option[A => B] = ???
你放什么代替???
? Some
?那么Some
呢?或None
?
答案 3 :(得分:0)
只需完成@svenningsson的答案即可。 其中一个特别有用的示例是在QuickCheck中生成随机函数。 此处的生成器定义为:
newtype Gen a = MkGen {
unGen :: QCGen -> Int -> a
}
它有一个Monad实例,该实例在某种意义上是Reader
,但其中bind
总是为所有子计算分配随机生成器。
这意味着我们可以定义一个作用在生成器上的函数,作为函数的生成器!
promote :: (a -> Gen b) -> Gen (a -> b)
promote f = MkGen $ \gen n -> \a -> let MkGen h = f a in h gen n
它在library中更为普遍。
现在的问题是如何获得一个首先作用于生成器的函数,但这是另一个很好的解释here的问题。