gpt4 book ai didi

haskell - 数据和新类型之间的惰性/严格性

转载 作者:行者123 更新时间:2023-12-02 11:43:07 25 4
gpt4 key购买 nike

我很难理解为什么这两个片段在所谓的“穷人严格分析”下会产生不同的结果。

第一个示例使用data(假设有正确的 Applicative 实例):

data Parser t a = Parser {
getParser :: [t] -> Maybe ([t], a)
}

> getParser (pure (,) <*> literal ';' <*> undefined ) "abc"
*** Exception: Prelude.undefined

第二个使用newtype。没有其他区别:

newtype Parser t a = Parser {
getParser :: [t] -> Maybe ([t], a)
}

> getParser (pure (,) <*> literal ';' <*> undefined ) "abc"
Nothing

literal x 是一个解析器,如果其参数与第一个标记匹配,则它会成功使用一个输入标记。因此,在此示例中,由于 ;a 不匹配,因此失败。但是,data 示例仍然发现下一个解析器未定义,而 newtype 示例则不然。

我已阅读 this , this ,和this ,但对它们的理解不够深入,无法理解为什么第一个示例未定义。在我看来,在这个例子中,newtype比data更懒,与答案相反。 (至少one other person也被这个搞糊涂了)。

为什么从 data 切换到 newtype 会改变此示例的定义?

<小时/>

这是我发现的另一件事:使用此 Applicative 实例,上面的 data 解析器输出未定义:

instance Applicative (Parser s) where
Parser f <*> Parser x = Parser h
where
h xs =
f xs >>= \(ys, f') ->
x ys >>= \(zs, x') ->
Just (zs, f' x')

pure a = Parser (\xs -> Just (xs, a))

而在这个实例中,上面的data解析器不会输出未定义的内容(假设Parser s有一个正确的 Monad 实例):

instance Applicative (Parser s) where
f <*> x =
f >>= \f' ->
x >>= \x' ->
pure (f' x')

pure = pure a = Parser (\xs -> Just (xs, a))
<小时/>

完整代码片段:

import Control.Applicative
import Control.Monad (liftM)

data Parser t a = Parser {
getParser :: [t] -> Maybe ([t], a)
}


instance Functor (Parser s) where
fmap = liftM

instance Applicative (Parser s) where
Parser f <*> Parser x = Parser h
where
h xs = f xs >>= \(ys, f') ->
x ys >>= \(zs, x') ->
Just (zs, f' x')

pure = return


instance Monad (Parser s) where
Parser m >>= f = Parser h
where
h xs =
m xs >>= \(ys,y) ->
getParser (f y) ys

return a = Parser (\xs -> Just (xs, a))


literal :: Eq t => t -> Parser t t
literal x = Parser f
where
f (y:ys)
| x == y = Just (ys, x)
| otherwise = Nothing
f [] = Nothing

最佳答案

您可能知道,data 之间的主要区别和newtypedata数据构造函数在 newtype 时是惰性的数据构造函数是严格的,即给出以下类型

data    D a = D a 
newtype N a = N a

然后D ⊥ `seq` x = x ,但是N ⊥ `seq` x = ⊥ .(其中 代表“底部”,即未定义的值或错误)

然而,可能不太为人所知的是,当您在这些数据构造函数上进行模式匹配时,角色“颠倒”,即

constD x (D y) = x
constN x (N y) = x

然后constD x ⊥ = ⊥ (严格),但是constN x ⊥ = x (懒)。

这就是您的示例中发生的情况。

Parser f <*> Parser x = Parser h where ...

data<*> 定义中的模式匹配如果出现以下任一情况,将立即发散参数为 ,但带有newtype构造函数被忽略,它是就像你写的一样

f <*> x = h where

只会出现 x = ⊥ 的分歧如果x是有要求的。

关于haskell - 数据和新类型之间的惰性/严格性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13566673/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com