首页 文章

R中函数调用的参数值的haskell样式模式匹配

提问于
浏览
1

在R中,是否可以根据参数值ala Haskell进行功能模式匹配?

即如果参数x是='foo',运行一个函数版本,如果x是'bar',运行另一个版本?显然,如果有必要,可以使用if语句来完成,但我想知道是否有更“实用”的方法 .

例如,要自动执行此类函数选择(foo1与foo2),而不使用ifelse语句进行调节:

foo1 <- function(a) {
    paste0(a, 'foo1')
}

foo2 <- function(a) {
    paste0('baz', a, 'foo2')
}

x <- 'barp'
value <- ifelse(x == 'barp', foo1(x), foo2(x))

2 回答

  • 1

    对于一般代数数据类型,您可以定义自己的匹配函数帮助程序 . 这些有时被称为“消除器”,并且实质上将您的ADT值转换为其教会编码 .

    例如,让我们翻译这个Haskell代码snipppet:

    x = Just 3
    y = Nothing
    a = case x of Nothing -> 42 ; Just w -> w+100
    b = case y of Nothing -> 42 ; Just w -> w+100
    

    结果是:

    # eliminator
    matchMaybe <- function(x,kn,kj) {
       ifelse(x[[1]]=='Nothing', kn(), kj(x[[2]]))
    }
    
    # tests
    x <- list('Just', 3)
    y <- list('Nothing')
    a <- matchMaybe(x
                   ,function() { 42 }
                   ,function(w){ w+100 })
    b <- matchMaybe(y
                   ,function() { 42 }
                   ,function(w){ w+100 })
    

    但请注意,深度模式匹配很难以这种方式转换 . 也就是说,在Haskell中你可以做类似的事情

    case x of Just 10 -> 22 ; Nothing -> 42 ; Just w -> w+100
    

    其中你同时匹配 Just 构造函数和内部 10 . 这不能以方便的方式编码 .

    对于字符串,如在OP示例中,可能的消除器可以是:

    match <- function(x,v,kt,ke) {
       ifelse(x==v, kt(),ke(x))
    }
    
    r <- match('foo'
         , 'bar', function() { "then" }
         ,        function(x) { "else" })
    

    另外请记住,我不熟练使用R,所以可能会有更好的方法 .

  • 1

    这可以基于对象的“类”来完成,但不能根据值来完成 . 我对Haskell并不是很熟悉,但是我虽然Haskell也调派类/类型而不是实际 Value ?这是R实现:

    > foo <- function(a) UseMethod("foo")
    > foo.1 <- function(a) paste(a, 'foo1')
    > foo.2 <- function(a) paste('baz', a, 'foo2')
    > 
    > obj_1 <- structure("hello world", class="1")
    > obj_2 <- structure("hello world", class="2")
    > 
    > foo(obj_1)
    [1] "hello world foo1"
    > foo(obj_2)
    [1] "baz hello world foo2"
    

    这只会根据第一个参数的类进行调度 . 如果要基于多个参数进行分派,可以使用S4方法 .

相关问题