How do Void and absurd work - purescript

Source code for Void states:
newtype Void = Void Void
instance showVoid :: Show Void where
show = absurd
absurd :: forall a. Void -> a
absurd a = spin a
where
spin (Void b) = spin b
It seems Void is an infinitely recursive type, while absurd is an infinitely recursive function. I tried running show ((unsafeCoerce "lol") :: Void) in the REPL and it promptly went into an infinite loop.
What bothers me here is the type signature of absurd :: forall a. Void -> a. How is the signature valid? Does the compiler recognize infinitely recursive functions and allow them to have any return type knowing they will never actually terminate if called? Wouldn't just having absurd = unsafeCoerce have the same effect?

No, the compiler doesn't recognize infinitely looping functions. That is actually known to be impossible - see Halting Problem.
The signature is valid, because there is nothing in the function body that would determine (or have any effect on) what the return type should be. Therefore, the return type can be anything. As simple as that.
The point of Void is that it's a type that cannot have any values at all. Like an empty set. In this case, that property is achieved via the clever trickery of making every value of Void contain another value of Void, thus making it impossible to construct a value of Void. This means that, for all practical purposes, the type Void cannot have any values.
The corresponding function absurd is a function that can never be called. This property follows from the function taking Void as argument. Since there can be no values of type Void, it is impossible to provide arguments for such function, and thus it is impossible to call it. Such function is useful in some very high-brow edge cases, but mostly it is a theoretical curiosity.

The implementation of absurd doesn't really matter, as it's not possible to have a value of Void - there's no way to construct it. That's also why it's safe to have such a function - it's not making something out of nothing, it just will never happen, so it's only used for evidence for the type checker. So yep, unsafeCoerce could also be used safely.
But yes, an infinitely recursive function can be typed as having whatever return type and that will type check - it's not a specific feature encoded in the type checker, it's just falls out from the other rules that we have. One way of looking at it, is since the function is infinitely recursive, there's no evidence to contradict whatever you state the return type as being.

Related

Why is the return type Unit used to describe operations that have no return value in Q#; as opposed to void or none?

Why did Microsoft, when creating Q#, decide to use the keyword Unit instead of void or none, to describe methods that have no return value? Is there a reason for this, or did Microsoft just want to do something different?
Functions and operations in Q# are always tuple-in tuple-out.
Together with singleton–tuple equivalence (the principle that 'T and ('T) are the exact same type), this lets Q# represent things uniformly, with every function and operation taking exactly one input and returning exactly one output, each of which are tuples.
One consequence of this approach that we can write a function like Composed<'T, 'U, 'V>(inner : ('T -> 'U), outer : ('U -> 'V)) : ('T -> 'V), confident that we can pass any function as inner, without thinking about how many arguments it takes.
For this design to be consistent, we need that a function or operation that "returns nothing" returns an empty tuple rather than no value at all. In many functional languages (including F#), the type of the empty tuple is called unit or Unit, following traditional notation in type theory. In Q#, we decided to follow that tradition to clarify the distinction between the value () and the type Unit.

How unsafe is it to cast an arbitrary function X=>Y to X => Unit in scala?

More explicitly, can this code produce any errors in any scenrios:
def foreach[U](f :Int=>U) = f.asInstanceOf[Int=>Unit](1)
I know it works, and I have a vague idea why: any function, as an instance of a generic type, must define an erased version of apply and jvm performs type check only when the object is actually to be returned to a code where it had a concrete type (often miles away). So, in theory, as long as I never look at the returned value, I should be safe. I don't have an enough low-level understandings of java byte code, let alone scalac, to have any certainty about it.
Why would I want to do it? Look at the following example:
val b = new mutable.Buffer[Int]
val ints = Seq(1, 2, 3, 4)
ints foreach { b += _ }
It's a typical scala construct, as far as imperative style can be typical. foreach in this example takes an Int as an argument, and as scalac knows it to be an Int, it will create a closure with a specialized apply(x :Int). Unfortunately, its return type in this case is a mutable.Buffer[Int], which is an AnyRef. As far as I was able to see, scalac will never invoke a specialized apply providing an AnyVal argument if the result is an AnyRef (and vice versa). This means, that even if the caller applies the function to Int, underneath the function will box the argument and invoke the erased variant. Here of course it doesn't matter as they are boxed within the List anyway, but I'm talking about the principle.
For this reason I prefer to define this type of method as foreach(f :X=>Unit), rather than foreach[O](f: X=>O) as it is in TraversableOnce. If the input sequence in the example had such a signature, everything would compile just as fine, and the compiler would ignore the actual type of the expression and generate a function with Unit return type, which - when applied to an unboxed Int - would invoke directly void apply(Int x), without boxing.
The problem arises with interoperability - sometimes I need to call a method expecting a function with a Unit return type and all I have is a generic function returning Odin knows what. Of course, I could just write f(_) to box it in another function object instead of passing it directly, but it to large extent makes the whole optimisation of small tight loops moot.

Would this function be allowed in Swift (if it wouldn't crash the compiler)

I got this function, which is a minimised version of an actual use case:
func f (i:Int) -> <T> (x:T) -> T {
return { x in return x }
}
As you see I would like to compute a generic function based on some input.
But as you can see in Xcode or on swiftstub, this function crashes the compiler.
Does anybody know if Swift is supposed to support such definitions?
This no longer crashes the compiler when I try it on 1.2b3. However, it’s not valid syntax.
If you want to return a function where the type is determined up-front at the time f is called, this would do it:
func f<T>(i:Int) -> T -> T {
return { x in return x }
}
// need to tell the compiler what T actually is...
let g = f(1) as Int->Int
g(2) // returns 2
However, Swift does not support the ability to define “generic” closures, i.e. closures where the type is determined not on creation of the closure, but at the point when that closure is actually called. This would require higher-ranked polymorphism, something that isn’t currently available (though maybe in the future, who knows – would be a very nice feature to have). For now, the placeholders need to be fully determined at the call site.
Keep in mind that the "generic" nature of Swift generics is kind of a misnomer. The genericness is just a template notation; all genericness is compiled away at compile time - that is, all generics used in one part of your code are resolved (specified) by the way they are called in another part of your code.
But for that very reason, you can't return a generic function as a result of a function, because there is no way to resolve the generic at compile time.
So, while crashing the compiler is not nice (and Apple would like to know about it), your code should not compile either, and to that extent the compiler is correct to resist.

What's the difference between Unit and Nothing?

Both types Unit and Nothing indicate a function that does not return anything. What's the difference between them?
Unit is a type that has exactly one value ‒ see Unit type. On the other hand, Nothing has no possible value - see Bottom type.
A function that doesn't return anything must have the return type Unit. If it were Nothing then the function could not return a result. The only way to exit the function would be by an exception.
Nothing is used in a different way. It is characterized by two properties:
Nothing is a subtype of every other type (including Null).
There exist no instances of this type.
When is this useful? Consider None:
object None extends Option[Nothing]
Because Option is covariant in its type parameter and Nothing is a subtype of everything, Option[Nothing] is a subtype of Option[A] for every type A. So, we can make one object None which is a subtype of Option[A] for every A. This is reasonable, since Nothing cannot be instantiated so Option[Nothing] will always be without a value. Similarly
object Nil extends List[Nothing]
Unit corresponds to logical true and Nothing corresponds to logical false under the Curry-Howard isomorphism, where we view types as propositions and functions as proofs, .
Unit means that (a) function has side effects like input and output, (b) these side effects are the main goal of the function. Of course, a function can have side effects even if its type is different from Unit.
Nothing is a special type in Scala, because (a) it has no values (Unit has exactly one value - ()), so you cannot return a value of type Nothing, and (b) it is a subtype of every other type. That means that if something has the type Nothing, it can be used instead of any other type (via subtyping), but it won't produce any result. This is useful for dealing with exceptions - the throw expression has a type of Nothing, so it can be used everywhere in a program.
Simply, Nothing means that there was an error or termination of a program and nothing was returned, while Unit means there were side effects, but execution ended normally with no result.
Programming in Scala has a nice explanation of that.
To add one aspect to Petr's reply: Nothing plays an important role in the type hierarchy. It is a bottom type. That means that it is a subtype of every other type, which is like the opposite of Any, which is a supertype of everything. You can find a nice explanation here.
Unit
Unit is same as void of Java. void in java is a keyword but Unit is an Object in Kotlin.
Now if a function returns Unit in Kotlin, it means that it doesn't return anything meaningful, that function just executes a bunch of code and gives back the execution flow.
Nothing
Nothing is a different kind altogether. You can't relate it with anything in Java. There is nothing as such as Nothing in java.
Nothing means the end of execution. If a function returns Nothing, means literally nothing it returns. Not even the execution flow.
Nothing is like a black hole, anything that goes in doesn't come out, Not even the light (light is "execution flow" here). In the case of Unit, least light comes out.
So, if a function returns Nothing, the flow of code ends there and anything written after that is Unreachable.
Now see the code below,
fun main() {
unitFun()
println("after unit")
nothingFun()
println("after nothing") //you get warning here saying "unreachable code"
}
fun nothingFun(): Nothing {
println("inside nothing")
throw Exception()
}
fun unitFun(): Unit {
println("inside unit")
}
Output will be
inside unit
after unit
inside nothing
Exception in thread "main" java.lang.Exception
NOTE: you get warning as soon as you write
println("after nothing") UnReachable Code
And you know the reason, it's because nothingFun doesn't even send back the execution flow.
One more thing to complete this here is, any function that returns Nothing has to throw an exception of any kind.
REASON: If you write some general statement (and not throw an exception) then the function will match the return type and we don't have anything that returns Nothing, means we don't have anything that sucks the execution flow and never returns it back. Everything returns something, even Unit is something.
Now, one can say that Nothing is a class so we can make object of it and return that itself. Nohhhhhhh? A big nohhhh?
Nothing class has one constructor but it is private, so you can't even make an object of it.
Last Bit
Behind the scene, Unit is converted into void(small v) in the decompiled byte code while Nothing is converted into Void(capital V).
see the below code,
var user = null //First
var user : User? =null //Second
Here, the Second statement shows, user of Nullable-User type.
What is the type of user of the first statement?
any guess?
It's Nullable-Nothing type.
try to see the first statement as
var user : Nothing? = null
Now what's happening under the hood,
Void user = (Void)null; //First
User user = (User)null; //Second

Relations between different functional programming notions

I understand different notions of functional programming by itself: side effects, immutability, pure functions, referential transparency. But I can't connect them together in my head. For example, I have the following questions:
What is the relation between ref. transparency and immutability. Does one implies the other?
Sometimes side effects and immutability is used interchangeably. Is it correct?
This question requires some especially nit-picky answers, since it's about defining common vocabulary.
First, a function is a kind of mathematical relation between a "domain" of inputs and a "range" (or codomain) of outputs. Every input produces an unambiguous output. For example, the integer addition function + accepts input in the domain Int x Int and produces outputs in the range Int.
object Ex0 {
def +(x: Int, y: Int): Int = x + y
}
Given any values for x and y, clearly + will always produce the same result. This is a function. If the compiler were extra clever, it could insert code to cache the results of this function for each pair of inputs, and perform a cache lookup as an optimization. That's clearly safe here.
The problem is that in software, the term "function" has been somewhat abused: although functions accept arguments and return values as declared in their signature, they can also read and write to some external context. For example:
class Ex1 {
def +(x: Int): Int = x + Random.nextInt
}
We can't think of this as a mathematical function anymore, because for a given value of x, + can produce different results (depending on a random value, which doesn't appear anywhere in +'s signature). The result of + can not be safely cached as described above. So now we have a vocabulary problem, which we solve by saying that Ex0.+ is pure, and Ex1.+ isn't.
Okay, since we've now accepted some degree of impurity, we need to define what kind of impurity we're talking about! In this case, we've said the difference is that we can cache Ex0.+'s results associated with its inputs x and y, and that we can't cache Ex1.+'s results associated with its input x. The term we use to describe cacheability (or, more properly, substitutability of a function call with its output) is referential transparency.
All pure functions are referentially transparent, but some referentially transparent functions aren't pure. For example:
object Ex2 {
var lastResult: Int
def +(x: Int, y: Int): Int = {
lastResult = x + y
lastResult
}
}
Here we're not reading from any external context, and the value produced by Ex2.+ for any inputs x and y will always be cacheable, as in Ex0. This is referentially transparent, but it does have a side effect, which is to store the last value computed by the function. Somebody else can come along later and grab lastResult, which will give them some sneaky insight into what's been happening with Ex2.+!
A side note: you can also argue that Ex2.+ is not referentially transparent, because although caching is safe with respect to the function's result, the side effect is silently ignored in the case of a cache "hit." In other words, introducing a cache changes the program's meaning, if the side effect is important (hence Norman Ramsey's comment)! If you prefer this definition, then a function must be pure in order to be referentially transparent.
Now, one thing to observe here is that if we call Ex2.+ twice or more in a row with the same inputs, lastResult will not change. The side effect of invoking the method n times is equivalent to the side effect of invoking the method only once, and so we say that Ex2.+ is idempotent. We could change it:
object Ex3 {
var history: Seq[Int]
def +(x: Int, y: Int): Int = {
result = x + y
history = history :+ result
result
}
}
Now, each time we call Ex3.+, the history changes, so the function is no longer idempotent.
Okay, a recap so far: a pure function is one that neither reads from nor writes to any external context. It is both referentially transparent and side effect free. A function that reads from some external context is no longer referentially transparent, whereas a function that writes to some external context is no longer free of side effects. And finally, a function which when called multiple times with the same input has the same side effect as calling it only once, is called idempotent. Note that a function with no side effects, such as a pure function, is also idempotent!
So how does mutability and immutability play into all this? Well, look back at Ex2 and Ex3. They introduce mutable vars. The side effects of Ex2.+ and Ex3.+ is to mutate their respective vars! So mutability and side effects go hand-in-hand; a function that operates only on immutable data must be side effect free. It might still not be pure (that is, it might not be referentially transparent), but at least it will not produce side effects.
A logical follow-up question to this might be: "what are the benefits of a pure functional style?" The answer to that question is more involved ;)
"No" to the first - one implies the other, but not the converse, and a qualified "Yes" to the second.
"An expression is said to be referentially transparent if it can be replaced with its value without changing the behavior of a program".
Immutable input suggests that an expression (function) will always evaluate to the same value, and therefore be referentially transparent.
However, (mergeconflict has kindly correct me on this point) being referentially transparent does not necessarily require immutability.
By definition, a side-effect is an aspect of a function; meaning that when you call a function, it changes something.
Immutability is an aspect of data; it cannot be changed.
Calling a function on such does imply that there can be no side-effects. (in Scala, that's limited to "no changes to the immutable object(s)" - the developer has responsibilities and decisions).
While side-effect and immutability don't mean the same thing, they are closely related aspects of a function and the data the function is applied to.
Since Scala is not a pure functional programming language, one must be careful when considering the meaning of such statements as "immutable input" - the scope of the input to a function may include elements other than those passed as parameters. Similarly for considering side-effects.
It rather depends on the specific definitions you use (there can be disagreement, see for example Purity vs Referential transparency), but I think this is a reasonable interpretation:
Referential transparency and 'purity' are properties of functions/expressions. A function/expression may or may not have side-effects. Immutability, on the other hand, is a property of objects, not functions/expressions.
Referential transparency, side-effects and purity are closely related: 'pure' and 'referentially transparent' are equivalent, and those notions are equivalent to the absence of side-effects.
An immutable object may have methods which are not referentially transparent: those methods will not change the object itself (as that would make the object mutable), but may have other side-effects such as performing I/O or manipulating their (mutable) parameters.