Raku中的Haskell型模式匹配

Raku中的Haskell型模式匹配,haskell,functional-programming,pattern-matching,raku,Haskell,Functional Programming,Pattern Matching,Raku,Haskell和Rust(以及我不知道的mabye其他语言)有一个他们称之为“模式匹配”的命运。以下是Haskell的一个例子: data Event=HoldKey Char | PressKey Char | Err String someFunc=let someEvent进程keySym 错误->退出错误 在Keepodingstaff 在Raku,最接近这一点的似乎是多方法多功能(术语在下面的答案中固定,但多方法也可以工作) 但是,如果我想要一个“本地”模式匹配表达式(如上面hask

Haskell和Rust(以及我不知道的mabye其他语言)有一个他们称之为“模式匹配”的命运。以下是Haskell的一个例子:

data Event=HoldKey Char | PressKey Char | Err String
someFunc=let
someEvent进程keySym
错误->退出错误
在Keepodingstaff
在Raku,最接近这一点的似乎是多方法多功能(术语在下面的答案中固定,但多方法也可以工作)

但是,如果我想要一个“本地”模式匹配表达式(如上面haskell代码片段中的
case
表达式),这就没有帮助了。大概是这样的:

given Hold.new(:key<a>) {
    when Hold (:$key)  { say $key }
    when Press (:$key) { say $key }
    when Err (:$msg)   { say $msg }
    default            { say "Unsupported" }
}
给定保持。新建(:键){
当按住(:$key){say$key}
按(:$key){说$key}
当Err(:$msg){say$msg}
默认值{say“Unsupported”}
}

这不是编译的。那么,我是否遗漏了什么,或者Raku是否可以用其他方式表达这一点?

您试图在不需要签名的情况下使用签名

签名更可能是块的一部分,因此看起来更像这样:

given Hold.new(:key<a>) {
    when Hold (:$key)  { say $key }
    when Press (:$key) { say $key }
    when Err (:$msg)   { say $msg }
    default            { say "Unsupported" }
}
给定保持。新建(:键){
当按住->(:$key){say$key}
按->(:$key){说$key}
当Err->(:$msg){say$msg}
默认值{say“Unsupported”}
}
这在当前不起作用,因为块没有任何参数

可以说,这将是一个需要添加的有用特性


请注意,
给定的
只做两件事

  • 像块一样执行
    继续
    成功
    以完成
  • $设置为您给定的值
  • 这意味着,
    $\uu
    已设置为您要智能匹配的值

    给定保持。新建(:键){
    何时按住{say.key}
    当按下{say.key}
    当Err{say.msg}
    默认值{say“Unsupported”}
    }
    
    您尝试的语法实际上非常接近。以下是您想要的:

    class Hold { has $.key; }
    class Press { has $.key; }
    class Err { has $.msg; }
    
    given Hold.new(:key<a>) {
        when Hold  { say .key }
        when Press { say .key }
        when Err   { say .msg }
        default { say "Unsupported" }
    }
    
    类保持{has$.key;}
    类Press{has$.key;}
    类Err{has$.msg;}
    给定保持。新建(:键){
    何时按住{say.key}
    当按下{say.key}
    当Err{say.msg}
    默认值{say“Unsupported”}
    }
    
    需要注意的几件事:正如语法的变化所显示的,您正在匹配
    Hold
    的类型,但您没有对
    Hold
    进行解构。相反,您正在利用这样一个事实,即
    块将块内的主题变量(
    $\ucode>)设置为与匹配项相等


    其次(看起来您已经意识到了这一点,但我将添加它以供将来参考),需要注意的是,
    给定的
    块不能保证穷举模式匹配。你可以用一个
    默认的{die}
    块来模拟这种保证,但这当然是一个运行时检查,而不是编译时检查。

    我同意在Raku中有优雅的语法会很好。但从功能上讲,我认为Raku比你想象的更接近你所描述的

    在拉库,最接近这一点的似乎是多重方法

    Raku确实支持多种方法。但你展示的是多功能

    我也认为多功能是Raku目前最接近你描述的东西。但我也认为他们比你现在认为的更接近


    我想要一个“本地”模式匹配表达式

    多功能是局部的(词汇范围)

    类保持{has$.key;}
    类Press{has$.key;}
    类Err{has$.msg;}
    { 
    匹配Hold.new::key;
    多重匹配(保持(:$key)){say$key}
    多重匹配(按(:$key)){say$key}
    多重匹配(Err(:$msg)){say$msg}
    多重匹配($){say“unsupported”}
    }
    
    #匹配;谢谢你的全面回答!我同意,在使用支持模式匹配的语言时,我非常喜欢依赖模式匹配。不过,你给出的另一种方法似乎已经相当强大了。这种特性在过去曾被推测过。从正在进行的dispatch工作到明年即将推出的新编译器前端,它的实现和性能可能会比今天更容易。是的,这就是我在上述评论中所说的“替代方法”,遗憾的是,无法访问更高级的模式匹配功能。您在类定义中缺少空格对齐方式,这让我很难受,默认块也是如此^_^查找“函数式编程”和“模式匹配”表明它只是语法上的糖分,具体的Raku示例可能会在上找到,尽管我希望@JonathanWorthington这样的人可能会纠正我,如果不是这样的话。请看:我想这就是@raiph在他的回答中所说的:模式匹配基本上已经通过多功能在Raku中出现了。在这一点上,我真正想要的是匿名表达式中的模式匹配,它可以使用synctatic sugar与Raku的多函数或C#s/C++s/Java/etc一起实现。。。访问者模式(如中所述)。不幸的是,Raku缺乏一个稳定的宏系统来自己实现这种糖(也被@raiph提到)。@jubilatious1只展示了
    给定的
    表达式,它并不真正支持完全模式匹配。对于任何对此感兴趣的人来说,这可能值得一读,通过使用多功能模式匹配和真正的代数数据类型(与我的bear类相反),这更进一步。此外,这也是一个很好的例子,说明了为什么Raku宏系统是一个非常好的主意haha@dincio“不幸的是,Raku缺乏一个稳定的宏系统来自己实现这个糖。”Fwiw一个人现在可以使用grarmmars/actions/slags,即非宏功能实现任何想要的语言变异。而且它至少是稳定的。也就是说,变更受st
    
    class Hold  { has $.key; }
    class Press { has $.key; }
    class Err   { has $.msg; }
    
    { 
      match  Hold.new: :key<a> ;
    
      multi match  (Hold  (:$key))  { say $key }
      multi match  (Press (:$key))  { say $key }
      multi match  (Err   (:$msg))  { say $msg }
      multi match  ($)              { say "unsupported" }
    }
    
    # match; <--- would be a compile-time fail if not commented out
    
    match Hold.new: :key<a>
      -> Hold  (:$key)  { say $key }
      -> Press (:$key)  { say $key }
      -> Err   (:$msg)  { say $msg }
      else              { say "unsupported" }