【问题标题】:haskell style pattern matching of parameter values for function calls in RR中函数调用的参数值的haskell样式模式匹配
【发布时间】:2015-03-29 02:32:23
【问题描述】:

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

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

例如,在不使用 ifelse 语句进行调节的情况下自动进行这种函数选择(foo1 vs. foo2):

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

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

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

【问题讨论】:

  • 为什么不用this 之类的?
  • 重点在于haskell,它可能是一个处理这两种情况的函数,根据参数值调度一种或另一种。我也在寻找 Haskell 的 R 等价物,而不是 Haskell 代码。
  • 我发现 this 似乎扩展了 R 以添加有限形式的模式匹配。
  • 有一个名为 lambda.r 的包,我认为它可以解决模式匹配和保护问题。

标签: r haskell pattern-matching


【解决方案1】:

对于一般代数数据类型,您可以定义自己的匹配函数助手。这些有时被称为“消除器”,基本上将您的 ADT 值转换为它们的 Church 编码。

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

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 })

但是请注意,deep 模式匹配很难以这种方式翻译。 也就是说,在 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,所以可能有更好的方法。

【讨论】:

  • 我必须承认我不熟悉教堂编码。这似乎有些复杂/复杂,但我想尝试实现模式匹配有点“与”语言“战斗”。
【解决方案2】:

这可以基于对象的“类”而不是值来完成。我对 Haskell 不是很熟悉,但我虽然 Haskell 也发送类/类型而不是实际值?这是 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 方法。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2016-04-26
  • 2015-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
相关资源
最近更新 更多