Haskell Foldr C实现

时间:2017-09-18 20:54:09

标签: c haskell

我试图在C中实现Haskell的折叠函数的一个版本但是已经碰到了一个墙,使它变得通用,因为我想使+或*字符(在foldr中的char)作为补充工作或乘法。我正在考虑尝试一个宏,但不确定什么会起作用。

这里是代码:

HashMap<String, MyModel> myHashMap;

主要问题是让char工作,所以我可以说:

int
foldr(int *v, int (*f)(int*), int x, char y)
{
    int temp;
    if(*v == (int) NULL) //v is null terminated int array
        return x;
    else{
        temp = *v;
        return temp y ((*f)(++v));
    }
}

它会起作用。 感谢

1 个答案:

答案 0 :(得分:1)

我将展示一种基于递归的方法。作为练习,如果您愿意,可以将其转换为迭代解决方案。

(警告:未经测试)

Haskell中:

foldr :: (Int->Int->Int) -> Int -> [Int] -> Int
foldr f x []     = x                    -- base case
foldr f x (v:vs) = f v (foldr f x vs)   -- recursion

C:

int foldr(int (*f)(int,int),
          int x,
          int *v, size_t length) {
    // base case
    if (length == 0) return x;
    // recursion
    return f(*v, foldr(f, x, v+1, length-1));
}

测试:

int add(int a, int b) {
   return a+b;
}
int main() {
   int a[] = {1,2,3} ;
   int res = foldr(add, 0, a, sizeof a/sizeof *a);
   printf("%d\n", res);
   return 0;
}

如果您传递上面的正确函数指针(如add),则无需传递字符运算符'+'

请注意,函数式编程语言也允许构建闭包,如:

let y = 5
in foldr (\x c -> x*y+c) 0 [1..3]

注意函数\x c -> x*y+c如何也取决于y的值。 C不允许执行工艺闭包,但如果允许C函数添加y参数,则可以模拟捕获的void *

int foldr(int (*f)(void *, int, int),
          void *data,
          int x,
          int *v, size_t length) {
    // base case
    if (length == 0) return x;
    // recursion
    return f(data, *v, foldr(f, data, x, v+1, length-1));
}

测试:

int g(void *data, int x, int c) {
   int y = *(int *)data;
   return x*y+c;
}
int main() {
   int a[] = {1,2,3} ;
   int y = 5;
   int res = foldr(g, &y, 0, a, sizeof a/sizeof *a);
   printf("%d\n", res);
   return 0;
}

通过这种方式,您可以将g重复使用y的不同值。如果需要捕获更多变量,请将指针传递给包含所有此类变量的合适struct