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

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.

Related

How are unused returned values handled in typed languages with type inference?

How do strongly typed languages that have type inference, handle the unused returned values (where it's not obvious what the intended type is)?
Here's an example where this happens in the untyped Python, where it's of course not caught:
list(map(lambda item: item.some_method, some_collection))
Here item.some_method was intended to be called, for its side effects, so the correct line is:
list(map(lambda item: item.some_method(), some_collection))
Without additional constraints, a strongly-typed language with type inference will typically not prevent the first example, as it is technically valid, as you point out. There are a few ways this could be avoided.
You could explicitly annotate the type of the map (or use it somewhere that forces the type to be equal to something). This would result in a type checking error if the wrong variant is used.
Some languages (e.g. Rust) distinguish between map and for_each, where the latter is expected to be impure/effectful. If you use for_each in the first example, this would fail to compile, as the type of lambda item: item.some_method is A -> () -> (), rather than A -> (). However, nothing prevents you from unidiomatically using map here.
Some languages (e.g. Haskell) distinguish between impure/effectful values and pure/effectless values. In this setting, map would be expected to take a lambda that is pure (making lambda item: item.some_method() invalid) and for_each would be expected to take a lambda that is impure (making lambda item: item.some_method invalid). This is enforced using monads, which act as a marker that tell the type system a value is impure (e.g. the type IO(A) represents an effectful A type).
Some languages (e.g. Rust) allow the use of values to be tracked and functions to be annotated to enforce their return values to be "used" in some way. If map is annotated #[must_use] in this way, then its return value must be used, which would alert you to an incorrect use of lambda item: item.some_method (as the return value of map would not be used). In Rust, the unit type () is automatically "used", and in theory this could be extended to include [()], in which case the correct code lambda item: item.some_method() would work without issues.

Can type constructors be considered as types in functional programming languages?

I am approaching the Haskell programming language, and I have a background of Scala and Java developer.
I was reading the theory behind type constructors, but I cannot understand if they can be considered types. I mean, in Scala, you use the keywords class or trait to define type constructors. Think about List[T], or Option[T]. Also in Haskell, you use the same keyword data, that is used for defining new types.
So, are type constructors also types?
Let's look at an analogy: functions. In some branches of mathematics, functions are called value constructors, because that's what they do: you put one or more values in, and they construct a new value out of those.
Type constructors are exactly the same thing, except on the type level: you put one or more types in, and they construct a new type out of those. They are, in some sense, functions on the type level.
Now, to our analogy: what is the analog of the question you are asking? Well, it is this: "Can value constructors (i.e. functions) be considered as values in functional programming languages?"
And the answer is: it depends on the programming language. Now, for functional programming languages, the answer is "Yes" for almost all (if not all) of them. It depends on your definition of what a "functional programming language" is. Some people define a functional programming language as a programming language which has functions as values, so the answer will be trivially "Yes" by definition. But, some people define a functional programming language as a programming language which does not allow side-effects, and in such a language, it is not necessarily true that functions are values.
The most famous example may be John Backus' FP, from his seminal paper Can Programming Be Liberated from the von Neumann Style? – a functional style and its algebra of programs. In FP, there is a hierarchy of "function-like" things. Functions can only deal with values, and functions themselves are not values. However, there is a concept of "functionals" which are "function constructors", i.e. they can take functions (and also values) as input and/or produce functions as output, but they cannot take functionals as input and/or produce them as output.
So, FP is arguably a functional programming language, but it does not have functions as values.
Note: functions as values is also called "first-class functions" and functions that take functions as input or return them as output are called "higher-order functions".
If we look at some types:
1 :: Int
[1] :: List Int
add :: Int → Int
map :: (a → b, List a) → b
You can see that we can easily say: any value whose type has an arrow in it, is a function. Any value whose type has more than one arrow in it, is a higher-order function.
Again, the same applies to type constructors, since they are really the same thing except on the type level. In some languages, type constructors can be types, in some they can't. For example, in Java and C♯, type constructors are not types. You cannot have a List<List> in C♯, for example. You can write down the type List<List> in Java, but that is misleading, since the two Lists mean different things: the first List is the type constructor, the second List is the raw type, so this is in fact not using a type constructor as a type.
What is the equivalent to our types example above?
Int :: Type
List :: Type ⇒ Type
→ :: (Type, Type) ⇒ Type
Functor :: (Type ⇒ Type) ⇒ Type
(Note, how we always have Type? Indeed, we are only dealing with types, so we normally don't write Type but instead simply write *, pronounced "Type"):
Int :: *
List :: * ⇒ *
→ :: (*, *) ⇒ *
Functor :: (* ⇒ *) ⇒ *
So, Int is a proper type, List is a type constructor that takes one type and produces a type, → (the function type constructor) takes two types and returns a type (assuming only unary functions, e.g. using currying or passing tuples), and Functor is a type constructor, which itself takes a type constructor and returns a type.
Theses "type-types" are called kinds. Like with functions, anything with an arrow is a type constructor, and anything with more than one arrow is a higher-kinded type constructor.
And like with functions, some languages allow higher-kinded type constructors and some don't. The two languages you mention in your question, Scala and Haskell do, but as mentioned above, Java and C♯ don't.
However, there is a complication when we look at your question:
So, are type constructors also types?
Not really, no. At least not in any language I know about. See, while you can have higher-kinded type constructors that take type constructors as input and/or return them as output, you cannot have an expression or a value or a variable or a parameter which has a type constructor as its type. You cannot have a function that takes a List or returns a List. You cannot have a variable of type Monad. But, you can have a variable of type Int.
So, clearly, there is a difference between types and type constructors.
Well, types and type constructors have a calculus of their own and they each have kinds. If you use :k (Maybe Int) in ghci for example, you'll get *, now this is a proper type and it (usually) has inhabitants. In this case Nothing, Just 42, etc. * now has a more descriptive alias Type.
Now you can look at the kind of the constructor that is Maybe, and :k Maybe will give you * -> *. With the alias, this is Type -> Type which is what you expect. It takes a Type and constructs a Type. Now if you see types as set of values, one good question is what set of values do Maybe has? Well, none because it is not really a type. You might attempt something like Just but that has type a -> Maybe a with kind Type, rather than Maybe with kind Type -> Type.
At least in Haskell, there is a hierarchy that can roughly be described as follows.
Terms are things that exist at run-time, values like 1, 'a', and (+), for example.
Each term has a type, like Int or Char or Int -> Int -> Int.
Each type has a kind, and all types have the same kind, namely *.
A type constructor like [], though, has kind * -> *, so it is not a type. Instead, it is a mapping from a type to a type.
There are other kinds as well, including (in addition to * and * -> *, with an example of each):
* -> * -> * (Either)
(* -> *) -> * -> * (ReaderT, a monad transformer)
Constraint (Num Int)
* -> Constraint (Num; this is the kind of a type class)

What is "value" in pure functional programming?

What constitutes a value in pure functional programming?
I am asking myself these questions after seeing a sentence:
Task(or IO) has a constructor that captures side-effects as values.
Is a function a value?
If so, what does it mean when equating two functions: assert(f == g). For two functions that are equivalent but defined separately => f != g, why don't they work as 1 == 1?
Is an object with methods a value? (for example IO { println("") })
Is an object with setter methods and mutable state a value?
Is an object with mutable state which works as a state machine a value?
How do we test whether something is a value? Is immutability a sufficient condition?
UPDATE:
I'm using Scala.
I'll try to explain what a value is by contrasting it with things that are not values.
Roughly speaking, values are structures produced by the process of evaluation which correspond to terms that cannot be simplified any further.
Terms
First, what are terms? Terms are syntactic structures that can be evaluated. Admittedly, this is a bit circular, so let's look at a few examples:
Constant literals are terms:
42
Functions applied to other terms are terms:
atan2(123, 456 + 789)
Function literals are terms
(x: Int) => x * x
Constructor invocations are terms:
Option(42)
Contrast this to:
Class declarations / definitions are not terms:
case class Foo(bar: Int)
that is, you cannot write
val x = (case class Foo(bar: Int))
this would be illegal.
Likewise, trait and type definitions are not terms:
type Bar = Int
sealed trait Baz
Unlike function literals, method definitions are not terms:
def foo(x: Int) = x * x
for example:
val x = (a: Int) => a * 2 // function literal, ok
val y = (def foo(a: Int): Int = a * 2) // no, not a term
Package declarations and import statements are not terms:
import foo.bar.baz._ // ok
List(package foo, import bar) // no
Normal forms, values
Now, when it is hopefully somewhat clearer what a term is, what was meant by "cannot be simplified any further*? In idealized functional programming languages, you can define what a normal form, or rather weak head normal form is. Essentially, a term is in a (wh-) normal form if no reduction rules can be applied to the term to make it any simpler. Again, a few examples:
This is a term, but it's not in normal form, because it can be reduced to 42:
40 + 2
This is not in weak head normal form:
((x: Int) => x * 2)(3)
because we can further evaluate it to 6.
This lambda is in weak head normal form (it's stuck, because the computation cannot proceed until an x is supplied):
(x: Int) => x * 42
This is not in normal form, because it can be simplified further:
42 :: List(10 + 20, 20 + 30)
This is in normal form, no further simplifications possible:
List(42, 30, 50)
Thus,
42,
(x: Int) => x * 42,
List(42, 30, 50)
are values, whereas
40 + 2,
((x: Int) => x * 2)(3),
42 :: List(10 + 20, 20 + 30)
are not values, but merely non-normalized terms that can be further simplified.
Examples and non-examples
I'll just go through your list of sub-questions one-by-one:
Is a function a value
Yes, things like (x: T1, ..., xn: Tn) => body are considered to be stuck terms in WHNF, in functional languages they can actually be represented, so they are values.
If so, what does it mean when equating two functions: assert(f == g) for two functions that are equivalent but defined separately => f != g, why don't they work as 1 == 1?
Function extensionality is somewhat unrelated to the question whether something is a value or not. In the above "definition by example", I talked only about the shape of the terms, not about the existence / non-existence of some computable relations defined on those terms. The sad fact is that you can't even really determine whether a lambda-expression actually represents a function (i.e. whether it terminates for all inputs), and it is also known that there cannot be an algorithm that could determine whether two functions produce the same output for all inputs (i.e. are extensionally equal).
Is an object with methods a value? (for example IO { println("") })
Not quite clear what you're asking here. Objects don't have methods. Classes have methods. If you mean method invocations, then, no, they are terms that can be further simplified (by actually running the method), so they are not values.
Is an object with setter methods and mutable state a value?
Is an object with mutable state which works as a state machine a value?
There is no such thing in pure functional programming.
What constitutes a value in pure functional programming?
Background
In pure functional programming there is no mutation. Hence, code such as
case class C(x: Int)
val a = C(42)
val b = C(42)
would become equivalent to
case class C(x: Int)
val a = C(42)
val b = a
since, in pure functional programming, if a.x == b.x, then we would have a == b. That is, a == b would be implemented comparing the values inside.
However, Scala is not pure, since it allows mutation, like Java. In such case, we do NOT have the equivalence between the two snippets above, when we declare case class C(var x: Int). Indeed, performing a.x += 1 afterwords does not affect b.x in the first snippet, but does in the second one, where a and b point to the same object. In such case, it is useful to have a comparison a == b which compares the object references, rather than its inner integer value.
When using case class C(x: Int), Scala comparisons a == b behave closer to pure functional programming, comparing the integers values. With regular (non case) classes, Scala instead compares object references breaking the equivalence between the two snippets. But, again, Scala is not pure. By comparison, in Haskell
data C = C Int deriving (Eq)
a = C 42
b = C 42
is indeed equivalent to
data C = C Int deriving (Eq)
a = C 42
b = a
since there are no "references" or "object identities" in Haskell. Note that the Haskell implementation likely will allocate two "objects" in the first snippet, and only one object in the second one, but since there is no way to tell them apart inside Haskell, the program output will be the same.
Answer
Is a function a value ? (then what it means when equating two function: assert(f==g). For two function that is equivalent but defined separately => f!=g, why not they work like 1==1)
Yes, functions are values in pure functional programming.
Above, when you mention "function that is equivalent but defined separately", you are assuming that we can compare the "references" or "object identities" for these two functions. In pure functional programming we can not.
Pure functional programming should compare functions making f == g equivalent to f x == g x for all possible arguments x. This is feasible when there is only a few values for x, e.g. if f,g :: Bool -> Int we only need to check x=True, x=False. For functions having infinite domains, this is much harder. For instance, if f,g :: String -> Int we can not check infinitely many strings.
Theoretical computer science (computability theory) also proved that there is no algorithm to compare two functions String -> Int, not even an inefficient algorithm, not even if we have access to the source code of the two functions. For this mathematical reason, we must accept that functions are values that can not be compared. In Haskell, we express this through the Eq typeclass, stating that almost all the standard types are comparable, functions being the exception.
Is an object with methods a value ? (for example, IO{println("")})
Yes. Roughly speaking, "everything is a value", including IO actions.
Is an object with setter methods and mutable states a value ?
Is an object with mutable states and works as a state machine a value ?
There is no mutable state in pure functional programming.
At best, the setters can produce a "new" object with the modified fields.
And yes, the object would be a value.
How do we test if it is a value, is that immutable can be a sufficient condition to be a value ?
In pure functional programming, we can only have immutable data.
In impure functional programming, I think we can call most immutable objects "values", when we do not compare object references. If the "immutable" object contains a reference to a mutable object, e.g.
case class D(var x: Int)
case class C(c: C)
val a = C(D(42))
then things are more tricky. I guess we could still call a "immutable", since we can not alter a.c, but we should be careful since a.c.x can be mutated.
Depending on the intent, I think that some would not call a immutable. I would not consider a to be a value.
To make things more muddy, in impure programming, there are objects which use mutation to present a "pure" interface in an efficient way. For instance one can write a pure function that, before returning, stores its result in a cache. When called again on the same argument, it will return the previously computed result
(this is usually called memoization). Here, mutation happens, but it is not observable from outside, where at most we can observe a faster implementation. In this case, we can simply pretend the that function is pure (even if it performs mutation) and consider it a "value".
The contrast with imperative languages is stark. In inperitive languages, like Python, the output of a function is directed. It can be assigned to a variable, explicitly returned, printed or written to a file.
When I compose a function in Haskell, I never consider output. I never use "return" Everything has "a" value. This is called "symbolic" programming. By "everything", is meant "symbols". Like human language, the nouns and verbs represent something. That something is their value. The "value" of "Pete" is Pete. The name "Pete" is not Pete but is a representation of Pete, the person. The same is true of functional programming. The best analogy is math or logic When you do pages of calculations, do you direct the output of each function? You even "assign" variables to be replaced by their "value" in functions or expressions.
Values are
Immutable/Timeless
Anonymous
Semantically Transparent
What is the value of 42? 42. What is the "value" of new Date()? Date object at 0x3fa89c3. What is the identity of 42? 42. What is the identity of new Date()? As we saw in the previous example, it's the thing that lives at the place. It may have many different "values" in different contexts but it has only one identity. OTOH, 42 is sufficient unto itself. It's semantically meaningless to ask where 42 lives in the system. What is the semantic meaning of 42? Magnitude of 42. What is the semantic meaning of new Foo()? Who knows.
I would add a fourth criterion (see this in some contexts in the wild but not others) which is: values are language agnostic (I'm not certain the first 3 are sufficient to guarantee this nor that such a rule is entirely consistent with most people's intuition of what value means).
Values are things that
functions can take as inputs and return as outputs, that is, can be computed, and
are members of a type, that is, elements of some set, and
can be bound to a variable, that is, can be named.
First point is really the crucial test whether something is a value. Perhaps the word value, due to conditioning, might immediately make us think of just numbers, but the concept is very general. Essentially anything we can give to and get out of a function can be considered a value. Numbers, strings, booleans, instances of classes, functions themselves, predicates, and even types themselves, can be inputs and outputs of functions, and thus are values.
IO monad is a great example of how general this concept is. When we say IO monad models side-effects as values, we mean a function can take a side-effect (say println) as input and return as output. IO(println(...)) separates the idea of the effect of an action of println from the actual execution of an action, and allows these effects to be considered as first class values that can be computed with using the same language facilities as for any other values such as numbers.

A type constructor IS a monad or HAS a monad?

People usually say a type IS a monad.
In some functional languages and libraries (like Scala/Scalaz), you have a type constructor like List or Option, and you can define a Monad implementation that is separated from the original type. So basically there's nothing that forbids you in the type system from creating distinct instances of Monad for the same type constructor.
is it possible for a type constructor to have multiple monads?
if yes, can you provide any meaningful example of that? any "artificial" one?
what about monoids, applicatives... ?
You can commonly find this all around in mathematics.
A monad is a triple (T, return, bind) such that (...). When bind and return can be inferred from the context, we just refer to the monad as T.
A monoid is a triple (M, e, •) such that (...). (...) we just refer to the monoid as M.
A topological space is a pair (S, T) such that (...). We just refer to the topological space as S.
A ring is a tuple (V, 0, +, 1, ×)...
So indeed, for a given type constructor T there may be multiple different definitions of return and bind that make a monad. To avoid having to refer to the triple every time, we can give T different names to disambiguate, in a way which corresponds to the newtype construct in Haskell. For example: [] vs ZipList, State s vs ReaderT s (Writer s).
P.S. There is something artificial in saying that a monad or a monoid is a triple, especially given that there are different presentations: we could also say that a monad is a triple (T, fmap, join), or that a monoid is a pair (M, •), with the identity element hidden in the extra condition (because it is uniquely determined by • anyway). The ontology of mathematical structures is a more philosophical question that is outside the scope of SO (as well as outside my expertise). But a more prudent way to reformulate such definitions may be to say that "a monad is (defined|characterized) by a triple (T, return, bind)".
Insofar as you're asking about language usage, Google says that the phrase “has a monad” doesn't seem to be commonly used in the way you're asking about. Most real occurrences are in sentences such as, “The Haskell community has a monad problem.” However, a few cases of vaguely similar usage do exist in the wild, such as, “the only thing which makes it ‘monadic‘ is that it has a Monad instance.” That is, monad is often used as a synonym for monadic, modifying some other noun to produce a phrase (a monad problem, a Monad instance) that is sometimes used as the object of the verb have.
As for coding: in Haskell, a type can declare one instance of Monad, one of Monoid and so on. When a given type could have many such instances defined, such as how numbers are monoids under addition, multiplication, maximum, minimum and many other operations, Haskell defines separate types, such as Sum Int, a Monoid instance over Int where the operation is +, and Product Int, a Monoid instance where the operation is *.
I haven't comprehensively checked the tens of thousands of hits, though, so it's very possible there are better examples in there of what you're asking about.
The phrasing I've commonly seen for that is the one I just used: a type is a category under an operation.

What is a "kind" in the context of Type Systems?

I have already read the Wikipedia article and searched for obvious places but I'm stuck. Can someone simple tell me what exactly is a Kind ? What is it used for ?
Scala examples are most appreciated
In short: a kind is to types what a type is to values.
What is a value? 1, 2, 3 are values. So are "Hello" and "World", true and false, and so forth.
Values belong to types. Types describe a set of values. 1, 2 and 3 belong to the type Nat, "Hello" and "World" to the type Text, true and false to the type Boolean.
Functions take one or more values as arguments and produce one or more values as results. In order to meaningfully do something with the arguments, the function needs to make some assumptions about them, this is done by constraining their types. So, function parameters and return values typically also have types.
Now, a function also has a type, which is described by the types of its inputs and outputs. For example, the abs function which computes the absolute value of a number has the type
Number -> NonNegativeNumber
The function add which adds two numbers has the type
(Number, Number) -> Number
The function divmod has the type
(Number, Number) -> (Number, Number)
Okay, but if functions take values as arguments and produce values as results, and functions are values, then functions can also take functions as arguments and return functions as results, right? What's the type of such a function?
Let's say we have a function findCrossing which finds the point where some other function (of numbers) crosses the y-axis. It takes as an argument the function and produces as a result a number:
(Number -> Number) -> Number
Or a function makeAdder which produces a function which takes a number and adds a specific number to it:
Number -> (Number -> Number)
And a function which computes the derivative of another function:
(Number -> Number) -> (Number -> Number)
Let's look at the level of abstraction here: a value is something very concrete. It only means one thing. If we were to order our levels of abstraction here, we could say that a value has the order 0.
A function, OTOH is more abstract: a single function can produce many different values. So, it has order 1.
A function which returns or accepts a function is even more abstract: it can produce many different functions which can produce many different values. It has order 2.
Generally, we call everything with an order > 1 "higher order".
Okay, but what about kinds? Well, we said above that 1, 2, "Hello", false etc. have types. But what is the type of Number? Or Text? Or Boolean?
Well, its type is Type, of course! This "type of a type" is called a kind.
And just like we can have functions which construct values out of values, we can have functions which construct types out of types. These functions are called type constructors.
And just like functions have types, type constructors have kinds. For example, the List type constructor, which takes an element type and produces a list type for that element has kind
Type -> Type
The Map type constructor, which takes a key type and a value type and produces a map type has kind
(Type, Type) -> Type
Now, continuing the analogy, if we can have functions which take functions as arguments, can we also have type constructors which take type constructors as arguments? Of course!
An example is the Functor type constructor. It takes a type constructor and produces a type:
(Type -> Type) -> Type
Notice how we always write Type here? Above, we had many different types like Number, Text, Boolean etc. Here, we always have only kind of type, namely Type. That gets tedious to (warning, bad pun ahead) type, so instead of writing Type everywhere, we just write *. I.e. Functor has the kind
(* -> *) -> *
and Number has the kind
*
Continuing the analogy, Number, Text and all others of kind * have order 0, List and all others of kind * -> * or more generally (*, …) -> (*, …) have order 1, Functor and all of kind (* -> *) -> * or * -> (* -> *) (and so forth) have order 2. Except in this case we sometimes also call it rank instead of order.
Everything above order/rank 1 is called higher-order, higher-rank or higher-kinded.
I hope the analogy is clear now: types describe sets of values; kinds describe sets of types.
Aside: I completely ignored currying. Basically, currying means that you can transform any function which takes two values into a function which takes one value and returns a function which takes the other value, similarly for three, four, five, … arguments. This means that you only ever need to deal with functions with exactly one parameter, which makes languages much simpler.
However, this also means that technically speaking, add is a higher-order function (because it returns a function) which is muddying the definitions.
The most eloquent explanation for kinds/higher-kinds I've seen so far and also in the context of Scala is Daniel Spiewak's High Wizardry in the Land of Scala. There are many versions, he gave this talk a few times, here I've chosen the longest one, but you can quickly google and find others.
The most important message from this talk is exactly the answer given by #Jörg W Mittag:
"kind is to types what a type is to values"
Another place for a more theoretical view on the subject is the paper Generics of a Higher Kind, also in the context of Scala.