【问题标题】:Haskell rare pattern matchingHaskell 稀有模式匹配
【发布时间】:2017-10-12 05:43:39
【问题描述】:

在haskell中,我可以做到:

s@"Hello" = s 

结果是:

>s
>"

它开始打印字符串但永远不会结束,这是怎么回事?

【问题讨论】:

    标签: haskell pattern-matching


    【解决方案1】:

    @"Hello" 在这里无关紧要,它所做的只是将类型固定为String。你会得到同样的行为

    s :: String
    s = s
    

    在语义上等价于

    s' :: String
    s' = undefined
    

    给出结果

    Prelude> s'
    "*** Exception: Prelude.undefined
    

    我所说的“语义等价”是指,ss' 都是底部值的示例,即来自“任何类型包含的错误值的sin bin”的值,这要归功于不严格”。一旦你达到最低值,纯粹的 Haskell 语言基本上是无能为力的,并且已经屈服于,嗯,undefined,“不纯行为”,比如让你永远等待或抛出异常。 p>

    但是,再次感谢非严格性,这不一定会发生。当打印一个值时,首先发生的是,Show 实例被调用并被要求生成一个字符串。 Haskell 字符串是一个惰性列表。而 any 字符串的show" 开头,因此即使字符串本身完全未定义,show 也会设法产生那个字符。

    我们可以更隐蔽地观察到这一点

    Prelude> head $ show s
    '"'
    

    【讨论】:

    • 哇,这个解释太完美了,这个问题我也能多理解一点,非常感谢!很高兴有大大师在这里闲逛
    【解决方案2】:

    lets 和顶级表达式中,= 左侧的所有内容都在右侧的范围内。所以你已经创建了一个循环的“底部”值。

    请注意,其行为方式相同:

    Prelude> let s = (s::String)
    Prelude> s
    "
    

    这是因为(简化)String 上的print 被定义为等同于:

    printString chars = putChar '"' >> mapM_ putChar chars
    

    因为chars 是一个循环,所以mapM_ putChar chars 似乎挂起。

    【讨论】:

    • 如果你在这里......当我试图调查这种行为时,我发现你可以在没有任何后果的情况下执行let 1=2。你能解释一下吗?
    • @Eugene:这与懒惰有关——只要你从不检查值,模式匹配就没有失败的机会。所以let x@1 = 2 in x 会失败,let !1 = 2 in () 也会失败。但是使用let 1 = 2 in (),没有什么会迫使 Haskell 实际执行请求的模式匹配。
    • 最后一个很有趣。虽然我认为 lhs 上不能有常量(和表达式)
    • 同样让 True = False in True?
    • @EugeneSh。另见:About `let 5 = 10`
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-13
    • 2021-05-22
    • 2017-05-08
    • 2019-03-01
    • 2016-10-29
    • 2011-11-30
    • 2019-05-17
    相关资源
    最近更新 更多