【问题标题】:Does <- implicitly coerce types in a Haskell do block?<- 是否隐式强制 Haskell 中的类型阻塞?
【发布时间】:2014-01-19 20:09:59
【问题描述】:

我的问题与另一个问题的答案有关:https://stackoverflow.com/a/11766789/3212958

在他的回答中,ertes 写了以下类型签名

select :: [a] -> [(a, [a])]

但是,当实际使用select 时,ertes 在do 块内写入以下内容

(y, ys) <- select xs

请帮助我了解元组 (y, ys) 如何匹配 select 的返回类型,即 [(a, [a])]。 Haskell 是否在某个时候强制使用类型? (Haskell 曾经强制类型吗?)&lt;- 是否从 select 返回的列表 monad 中提取类型为 (a, [a]) 的元组?

谢谢, 最大

--- 编辑:---

@Lee 提醒新手在尝试推理类型之前先脱糖。在明确&gt;&gt;= 之后,更清楚发生了什么。脱糖后,有问题的函数如下所示:

select xs >>= \(y, ys) -> fmap (y:) (perms (n - 1) ys)

对于列表,xs &gt;&gt;= f = concat (map f xs)。因此,在这种情况下,更好地阅读 (y, ys) 是作为映射列表的函数的签名。

【问题讨论】:

  • select 返回一个列表。如果你写a &lt;- select xs,那么a 就是select xs 的每个元素。如果您稍后编写func a,其结果是将func 应用于select xs 的每个元素的结果。这就是 list monad 的定义方式。 a &lt;- select xs; func aselect xs &gt;&gt;= func 相同。绑定列表定义为:m &gt;&gt;= f = concat (map f m),所以你写的是map func (select xs)。 haskell 中没有类型强制。
  • @user2407038 这里有点技术性; a 不是“每个元素”,a 代表列表中的 一个(任意但特定)元素。

标签: haskell types monads


【解决方案1】:

do 表示法中,

do x1 <- action1
   action2

翻译成action1 &gt;&gt;= \x1 -&gt; action2

这意味着如果action1 对某些monad m 具有m a 类型,那么x1 具有a 类型。这并不是真正的强制类型,而是从单子操作action1 中“解包”值并将其绑定到x1

【讨论】:

    【解决方案2】:

    (y, ys) 的类型为 (b, c)

    select 的返回类型是 [(a, [a])] 类型

    &lt;- 中,类型实际上是dMonad m =&gt; m d。所以我们可以写出以下类型等式:

    (b, c) ~ d
    [(a, [a])] ~ Monad m => m d
    

    求解很容易。首先将d 从第一个方程代入第二个方程:

    [(a, [a])] ~ Monad m => m (b, c)
    

    现在看看发生了什么,我将使用 [] 类型构造函数的前缀形式(它不是有效的 haskell,但你应该明白):

    [] (a, [a]) ~ Monad m => m ( b, c)
    

    所以

    m ~ []
    (a, [a]) ~ (b, c)
    

    此时编译器检查instance Monad [a] 是否存在。剩下的很简单:

    a ~ b
    [a] ~ c
    

    【讨论】:

    • [] (a, [] a) 实际上是有效的 Haskell,如果你愿意,甚至是 [] ((,) a ([] a))
    • 哦,我不知道[]的类型构造函数可以这样使用,就像值构造函数一样。
    • 是的,我也很惊喜地了解到它。当然更容易解释 list monad。
    猜你喜欢
    • 2019-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-18
    • 2020-09-16
    • 2011-04-09
    • 2017-01-25
    • 1970-01-01
    相关资源
    最近更新 更多