T
T
thewizardplusplus2015-06-24 19:43:14
JavaScript
thewizardplusplus, 2015-06-24 19:43:14

How to implement a variadic pure function without type classes?

The essence of the problem is as follows. I want to create a variadic function for creating a list/array:
list(1)(2)(3)(4)(5)() === [1, 2, 3, 4, 5]
But for simplicity of reasoning, let's take a variadic addition function (just not to think about the atomic operation of constructing a list from head and tail for now):
sum(1)(2)(3)(4)(5)() === 1 + 2 + 3 + 4 + 5 === 15
Actually, I found a Haskell solution ( stackoverflow.com/questions /3467279/how-to-create-... ):

class SumRes r where
    sumOf :: Integer -> r

instance SumRes Integer where
    sumOf = id

instance (Integral a, SumRes r) => SumRes (a -> r) where
    sumOf x = sumOf . (x +) . toInteger

sumOf 1 4 7 10 2 5 8 22 == 59

But it uses type classes. I need simple lambda functions.
Type classes are needed in Haskell because it is a statically strongly typed language. Let's assume that we have a dynamic language - JavaScript. Therefore, in theory, it should be possible to implement this without type classes (more precisely, simulate their work through conditions and checking the types of arguments). But unfortunately I can't figure out how to do it.
Main restrictions:
  • the purity of the function - there should be no external or internal accumulator variables, the solution is important in terms of pure lambda functions, i.e. without the presence of a stored state;
  • the arity of a function (and all that it returns) must be 1 (i.e. they must take only 1 argument).

In fact, I want to convert the above Haskell code to JavaScript code, subject to restrictions.
Perhaps I do not fully understand what type classes are, but it seems like in this case they make a function overload according to the type of its result! This is not possible in other languages ​​(although it can be simulated by something else).
Help me please.

Answer the question

In order to leave comments, you need to log in

2 answer(s)
T
thewizardplusplus, 2015-06-24
@thewizardplusplus

While describing the problem, he understood how to solve it. ))

function add(x) {
  return function(y) {
    return x + y;
  };
}

function sum(a) {
  return function(b) {
    if (b) {
      return sum(add(a)(b));
    } else {
      return a;
    }
  };
}

sum(1)(2)(3)(4)(5)() === 15

function cons(x) {
  return function(y) {
    return [x, y];
  };
}

function list(a) {
  return function(b) {
    if (b) {
      return list(cons(a)(b));
    } else {
      return a;
    }
  };
}

list(1)(2)(3)(4)(5)() === ]

Although the list is still created in reverse order.

Y
Yuri Puzynya, 2015-06-24
@3y3

Are you sure you wanted to get just such an array?
Regarding the same amount, I will give you an interesting idea to play around with:

function sum(a) {
  var sum = a;
  
  function _sum(b) {
    if (b === undefined) return sum;
    
    sum += b;
    return _sum;
  }
  
  _sum.toString = function() {
    return sum;
  };
  
  return _sum;
}

sum(1)(2)(3) + sum(2)(2) + sum(sum(1)(2)(3))(4)(5); // 25

Some differences in this implementation:
1. New functions are created a little less often (you have a new function every time you call it).
2. The last call is not necessary to get the value. Those. it is also possible to get an intermediate value and continue the calculations. In general, if you are sure that only numbers will participate in operations, it would be more correct to define valueOf, but toString is more universal.
3. Your implementation doesn't take into accountsum(1)(2)(0)(3)()

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question