Scala 转向A=>;M[B]到M[A=>;B]
对于单子Scala 转向A=>;M[B]到M[A=>;B],scala,haskell,types,monads,scalaz,Scala,Haskell,Types,Monads,Scalaz,对于单子M,是否可以将a=>M[B]转换为M[a=>B] 我试着按照这些类型去做,但没有效果,这让我觉得这是不可能的,但我想我还是会问的。另外,在Hoogle中搜索a->mb->m(a->b)也没有返回任何结果,所以我没有太多运气。实际上 不,这是不可能的,至少不是以一种有意义的方式 考虑这个Haskell代码 action::Int->IO字符串 操作n=打印n>>获取行 这将首先获取n,打印它(此处执行IO),然后从用户处读取一行 假设我们有一个假设的转换::(a->iob)->IO(a-
M
,是否可以将a=>M[B]
转换为M[a=>B]
我试着按照这些类型去做,但没有效果,这让我觉得这是不可能的,但我想我还是会问的。另外,在Hoogle中搜索a->mb->m(a->b)
也没有返回任何结果,所以我没有太多运气。实际上
不,这是不可能的,至少不是以一种有意义的方式
考虑这个Haskell代码
action::Int->IO字符串
操作n=打印n>>获取行
这将首先获取n
,打印它(此处执行IO),然后从用户处读取一行
假设我们有一个假设的转换::(a->iob)->IO(a->b)
。然后,作为一个心理实验,考虑:
action':IO(Int->String)
动作'=变换动作
在知道n
之前,上面必须提前执行所有IO,然后返回纯函数。这不能等同于上面的代码
强调这一点,请考虑下面的无意义代码:
测试::IO()
试验=DofNo
例如,Option
是一个monad,但是函数(a=>Option[B])=>Option[a=>B]
没有有意义的实现:
def transform[A, B](a: A => Option[B]): Option[A => B] = ???
你用什么代替
?
<代码>一些<代码>一些然后呢?或者None
?其他回答很好地说明,一般来说,对于任何单子m
,都不可能实现从a->mb
到m(a->b)
的功能。然而,有一些特定的单子可以实现这个功能。一个例子是读卡器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
只是为了完成@svenningsson的回答。 其中一个特别有用的例子是在快速检查中生成随机函数。 此处的发电机定义为:
newtype Gen a = MkGen {
unGen :: QCGen -> Int -> a
}
它有一个实例,在某种意义上是Reader
,但是bind
总是为所有子计算拆分随机生成器
这意味着我们可以将作用于生成器的函数定义为函数生成器
promote :: (a -> Gen b) -> Gen (a -> b)
promote f = MkGen $ \gen n -> \a -> let MkGen h = f a in h gen n
而且,它在世界范围内更为普遍
现在的问题是如何得到一个作用于生成器的函数,但这是另一个问题,已经很好地解释过了 @user5402
transform
是OP@user5402以上事实表明,transform
无法实现。@user5402它可以存在于某些特定的单子(例如Reader),但不能存在于所有的单子(例如IO)。@chi:你能推荐一本书,让我们了解更多关于Curry Howard,Peirce定律,等西蒙·汤普森(Simon Thompson)的《类型理论与函数式编程》(1991)仍然相关吗?@Zeta在我看来,这本书很好。我不知道关于一般和更高级材料的书。我想亲眼看看。一些普遍的事实可以在Coq的书或HoTT的书中找到,尽管这些书的目的更加精确。我还建议学习割消法和序列演算——否则我无法证明皮尔斯定律在IPC中是不可证明的。尽管答案是正确的,但要注意“缺乏想象力的证明”。(旁注:你真的想要Monad m=>(a->m b)->m(a->b)
来自Hoogle。请注意额外的括号,意思是一个参数而不是“两个”。当然,正如chi所证明的,除了使用bottom之外,该类型不会被占用,因此您仍然不会得到任何结果。)
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
newtype Gen a = MkGen {
unGen :: QCGen -> Int -> a
}
promote :: (a -> Gen b) -> Gen (a -> b)
promote f = MkGen $ \gen n -> \a -> let MkGen h = f a in h gen n