Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot create apply function with static language?

Tags:

I have read that with a statically typed language like Scala or Haskell there is no way to create or provide a Lisp apply function:

(apply #'+ (list 1 2 3)) => 6 

or maybe

(apply #'list '(list :foo 1 2 "bar")) => (:FOO 1 2 "bar") (apply #'nth (list 1 '(1 2 3))) => 2 

Is this a truth?

like image 441
Eli Schneider Avatar asked Sep 12 '10 02:09

Eli Schneider


People also ask

Is java static or dynamic language?

Java is statically-typed, so it expects its variables to be declared before they can be assigned values. Groovy is dynamically-typed and determines its variables' data types based on their values, so this line is not required.

Is C statically-typed language?

A statically-typed language is a language (such as Java, C, or C++) where variable types are known at compile time.

Is go statically-typed?

Go is a strongly, statically typed language. There are primitive types like int, byte, and string. There are also structs. Like any strongly typed language, the type system allows the compiler helps catch entire classes of bugs.

What is static programming?

Statically Typed Languages This means that before source code is compiled, the type associated with each and every single variable must be known. Some common examples of programming languages that belong to this category are Java, Haskell, C, C++, C#, Scala, Kotlin, Fortran, Go, Pascal, and Swift.


1 Answers

It is perfectly possible in a statically typed language. The whole java.lang.reflect thingy is about doing that. Of course, using reflection gives you as much type safety as you have with Lisp. On the other hand, while I do not know if there are statically typed languages supporting such feature, it seems to me it could be done.

Let me show how I figure Scala could be extended to support it. First, let's see a simpler example:

def apply[T, R](f: (T*) => R)(args: T*) = f(args: _*) 

This is real Scala code, and it works, but it won't work for any function which receives arbitrary types. For one thing, the notation T* will return a Seq[T], which is a homegenously-typed sequence. However, there are heterogeneously-typed sequences, such as the HList.

So, first, let's try to use HList here:

def apply[T <: HList, R](f: (T) => R)(args: T) = f(args) 

That's still working Scala, but we put a big restriction on f by saying it must receive an HList, instead of an arbitrary number of parameters. Let's say we use @ to make the conversion from heterogeneous parameters to HList, the same way * converts from homogeneous parameters to Seq:

def apply[T, R](f: (T@) => R)(args: T@) = f(args: _@) 

We aren't talking about real-life Scala anymore, but an hypothetical improvement to it. This looks reasonably to me, except that T is supposed to be one type by the type parameter notation. We could, perhaps, just extend it the same way:

def apply[T@, R](f: (T@) => R)(args: T@) = f(args: _@) 

To me, it looks like that could work, though that may be naivety on my part.

Let's consider an alternate solution, one depending on unification of parameter lists and tuples. Let's say Scala had finally unified parameter list and tuples, and that all tuples were subclass to an abstract class Tuple. Then we could write this:

def apply[T <: Tuple, R](f: (T) => R)(args: T) = f(args) 

There. Making an abstract class Tuple would be trivial, and the tuple/parameter list unification is not a far-fetched idea.

like image 60
Daniel C. Sobral Avatar answered Oct 09 '22 07:10

Daniel C. Sobral