如何在 Raku 中制作函数链运算符?

问题描述 投票:0回答:1

出于学习目的,我尝试将此 F# 代码翻译为 Raku:

type Meat = Chicken | Beef | Pork | Fish | Veggie

type Ingredient =
    | Cheese | Rice | Beans | Salsa | Guacamole | SourCream | Lettuce
    | Tomato | Onion | Cilantro | PicoDeGallo

type Burrito = Meat option * Ingredient list

let (>>=) burrito f =
    match burrito with
    | Some meat, ingredients -> f (Some meat, ingredients)
    | None, _ -> None, []

let returnBurrito (meat, ingredients) = meat, ingredients

let tortilla = returnBurrito (Some Veggie, [])

let addMeat meat (m, ingredients) = Some meat, ingredients

let addIngredient ingredient (meat, ingredients) =
    meat, ingredient :: ingredients

let addMissionBurritoIngredients (meat, ingredients) =
    meat, Cheese :: Rice :: Beans :: ingredients

let holdThe ingredient (meat, ingredients) =
    meat, List.filter (fun i -> i <> ingredient) ingredients

let burrito =
    tortilla
    >>= addMeat Chicken
    >>= addMissionBurritoIngredients
    >>= holdThe Cheese
    >>= addIngredient PicoDeGallo
    >>= addIngredient Salsa
    >>= addIngredient Guacamole
    >>= addIngredient SourCream

printfn "%A" burrito

到目前为止,在 Raku 中,我有这个工作代码(但它通常不可链接):

use Monad::Result;

enum Meat <Chicken Beef Pork Fish Veggie>;

enum Ingredient <Cheese Rice Beans Salsa Guacamole SourCream Lettuce Tomato Onion Cilantro PicoDeGallo>;

sub returnBurrito($meat, @ingredients) { $meat, @ingredients }

sub tortilla { returnBurrito( Monad::Result.ok(Veggie), [] ) }

sub add-meat($meat, ($, @ingredients)) { Monad::Result.ok($meat), @ingredients }

sub add-ingredient($ingredient, ($meat, @ingredients)) {
    $meat, [$ingredient, |@ingredients]
}

sub add-mission-burrito-ingredients(($meat, @ingredients)) {
    $meat, [Cheese, Rice, Beans, |@ingredients]
}

sub hold-the($ingredient, ($meat, @ingredients)) {
    ($meat, [@ingredients.grep(* != $ingredient)]);
}

my $burrito = tortilla;
say $burrito;

sub zz( $burrito, &f ) {
    -> $meat { &f( $meat, $burrito ) }
}

say zz($burrito, &add-meat);
say zz($burrito, &add-meat)(Beef);

问题是我无法弄清楚如何使链接操作作为中缀工作。

我已经尝试过这个尝试:

sub infix:<xx>( $burrito, &f ) {
    -> $meat { &f( $meat, $burrito ) }
}

say ($burrito xx &add-meat);
say ($burrito xx &add-meat)(Beef);

但它给出了错误:

(Ok ( Veggie ) [])
-> $meat { #`(Block|5635547097056) ... }
Cannot unpack or Capture `Code.new`.
To create a Capture, add parentheses: \(...)
If unpacking in a signature, perhaps you needlessly used parentheses? -> ($x) {} vs. -> $x {}
or missed `:` in signature unpacking? -> &c:(Int) {}
  in sub add-meat at burrito.raku line 11
  in block <unit> at burrito.raku line 29
functional-programming f# raku
1个回答
0
投票

这是更正后的代码,消除了使用

xx
作为占位符...

use Monad::Result;

enum Meat <Chicken Beef Pork Fish Veggie>;

enum Ingredient <Cheese Rice Beans Salsa Guacamole SourCream Lettuce Tomato Onion Cilantro PicoDeGallo>;

sub returnBurrito($meat, @ingredients) { $meat, @ingredients }

sub tortilla { returnBurrito( Monad::Result.ok(Veggie), [] ) }

sub add-meat($meat, ($, @ingredients)) { Monad::Result.ok($meat), @ingredients }

sub add-ingredient($ingredient, ($meat, @ingredients)) {
    $meat, [$ingredient, |@ingredients]
}

sub add-mission-burrito-ingredients(($meat, @ingredients)) {
    $meat, [Cheese, Rice, Beans, |@ingredients]
}

sub hold-the($ingredient, ($meat, @ingredients)) {
    ($meat, [@ingredients.grep(* != $ingredient)]);
}

sub infix:«>>=»( $burrito, &f ) {
    given $burrito {
        when *.is-ok,    $ {
            -> $arg=Empty { &f( |($arg, $burrito) ) }
        }
        when *.is-error, $ {
            (Monad::Result.error('None'), [])
        }
    }
}

my \burrito =
    (((((((tortilla()
        >>= &add-meat)(Chicken)
        >>= &add-mission-burrito-ingredients)()
        >>= &hold-the)(Cheese)
        >>= &add-ingredient)(PicoDeGallo)
        >>= &add-ingredient)(Salsa)
        >>= &add-ingredient)(Guacamole)
        >>= &add-ingredient)(SourCream)
;

say burrito;
#(Ok ( Chicken ) [SourCream Guacamole Salsa PicoDeGallo Rice Beans])

总体而言,我认为 F# 的这种相当快速的翻译非常忠实于最初的意图,尽管摘要中使用

Empty
和 LISP 风格的括号可能是可以通过更多思考来做得更好的领域。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.