Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 转向A=>;M[B]到M[A=>;B]_Scala_Haskell_Types_Monads_Scalaz - Fatal编程技术网

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