Can I use floating point enums in Frege? - frege

I tried
println [1.0, 1.25..2.0]
but got
Double is not an instance of Enum
I couldn't find this issue in the "differences to Haskell", though.
Is there a recommended alternative?

You're right that it should be in the "Differences".
For an alternative, consider
iterate :: (a -> a) -> a -> [a]
So, to get your list above, write:
takeWhile (<=2.0) (iterate (+0.25) 1)
It should also be possible to make Double and Float instances of Enum.
There is simply lots of work to do in the field of numeric types and type classes.

Related

Understanding Kotlin Type system, What is meant by `{Comparable<{ Double & Int }> & Number}` and how to work with that

So for example:
var a = true
val test = if (a) -1 else -3.2
I was expecting the Type of the test should be the most closest intersection of the type-hierarchy i.e. for Int and Double is Number.
But looking at the IDE, it seems to have a type of {Comparable<{ Double & Int }> & Number}.
And the weird thing is, I cannot specify it like that (since {} is reserved for creating lambdas), I can only set it to a type of Number.
And another wierd thing is that if I try some function from Comparable interface, it throws some error:
// Warning at value 2
// The integer literal does not conform to the expected type {Double & Int}
test.compareTo(2)
3.compareTo(-1.1) // possible
2.3.compareTo(100) // possible
// But why not this is possible, while it has inferred type of Comparable?
test.compareTo(2)
Could somebody help in understanding the concept here? And few questions:
How does that type work all together, i.e. how could one variable hold two types at once?
How could one specify that type explicitly?
How do you use functions from Comparable interface, when test has implementaion of it?
& here means an intersection type (which isn't supported in the Kotlin language itself, but the compiler uses them internally). You can see it mentioned in the (incomplete) specification.
Intersection types are special non-denotable types used to express the fact that a value belongs to all of several types at the same time.
"Non-denotable" means exactly that you can't specify that type. I am not sure but I think the extra { } in types are supposed to indicate exactly this.
In particular, Comparable<Double & Int> means you can only compare test to something which is both Double and Int, but there are no such values. The compiler could probably simplify it to Comparable<Nothing>.
the most closest intersection of the type-hierarchy i.e. for Int and Double is Number.
It's least upper bound, which is closer to union, not intersection. The specification actually calls it "union types", but that's not the normal usage of that term.
This least upper bound is not Number because it also takes least upper bound of the Comparable interfaces which works out to Comparable<Double & Int> because Comparable is contravariant:
lub(Int, Double) =
Number & lub(Comparable<Int>, Comparable<Double>) =
Number & Comparable<Int & Double>
This calculation is described under type decaying:
All union types are subject to type decaying, when they are converted to a specific intersection type, representable within Kotlin type system.
The answer to question 1 is that the compiler is doing its best to infer the type, inventing new constraints to describe it as it goes.
The answer to question 2 is that you cannot.
The answer to question 3 is that you cannot, because Int is not comparable to Double and vice versa. So none of the methods from Comparable are actually usable, but the value definitely implements Comparable against something. This is not useful for Comparable, but could be for another interface. For example, imagine:
interface ZeroAndComparable<T> {
fun compareTo(t: T): Int
fun zero(): T
}
val foo : ZeroAndComparable<Int> = someZeroAndComparableInt()
val bar : ZeroAndComparable<Double> = someZeroAndComparableDouble()
val foobar = if (a) foo else bar
val zero : Any = foobar.zero() // should work
foobar.compareTo(something) // cannot work

List.sum in Core, don't understand containers

I'm trying to understand List.sum from Jane streets core. I got it to work on a simple list of integers, but don't understand the concepts of Core's containers, and find the api documentation to terse to understand. Here's some code that works:
#require "core";;
open Core;;
List.sum (module Int) [1;2;3] ~f:ident;;
- : int = 6
#show List.sum;;
val sum :
(module Base__.Container_intf.Summable with type t = 'sum) ->
'a list -> f:('a -> 'sum) -> 'sum
Why do I have to use module Int and the identity function. [1;2;3] already provides a type of int list. Is there any good information about the design ideas behind Core?
The module provides the means of summing the values in question. The f provides a transformation function from the type of elements in the list to the type of elements you want to sum.
If all you want want to do is sum the integers in a list, then the summation function desired is in the Int module (thus we need module Int) and the transformation function is just ident (because we needn't transform the values at all).
However, what if you wanted obtain a sum of integers, but starting with a list of strings representing integers? Then we would have
utop # List.sum (module Int) ["1";"2";"3";"4"];;
- : f:(string -> int) -> int = <fun>
i.e., if we want to sum using the module Int over a list of strings, then we'll first need a function that will convert each value of type string to a value of type int. Thus:
utop # List.sum (module Int) ["1";"2";"3";"4"] ~f:Int.of_string;;
- : int = 10
This is pretty verbose, but it gives us a lot of flexibility! Imagine trying to sum using a different commutative operation, perhaps over a particular field in a record.
However, this is not the idiomatic way to sum a list of integers in OCaml. List.sum is a specific function which the List module "inherits" by virtue of it satisfying the a container interface used in the library design of Base (which provides the basic functionality of Core. The reason this function is relatively complex to use is because it is the result of a highly generalized design over algebraic structures (in this case, over collections of elements which can be transformed in elements which have a commutative operation defined over them).
For mundane integer summation, OCamlers just use a simple fold:
utop # List.fold [1;2;3;4] ~init:0 ~f:(+);;
- : int = 10
One good place to look for some insight into the design decisions behind Core is https://dev.realworldocaml.org/ . Another good resource is the Janestreet tech blog. You might also consult the Base repo (https://github.com/janestreet/base) or post a question asking for more specific details on the design philosophy in https://discuss.ocaml.org/
Janestreet's libraries have been notoriously opaque to newcomers, but they are getting a lot better, and the community will be happy to help you learn.
Tho the documentation is terse, it is very expressive. In particular, it tends to rely on the types to carry much of the weight, which means the code is largely self-documenting. It takes some practice to learn to read the types well, but this is well worth the effort, imo, and carries its own rewards!

How does slice indexing work in Rust?

I wondered what slices were in Rust. As it turned out, it's just a struct with a data pointer and the size inside. I've looked at the source for indexing and I've found this:
impl<T> ops::Index<usize> for [T] {
type Output = T;
fn index(&self, index: usize) -> &T {
// NB built-in indexing
&(*self)[index]
}
}
I'm not a Rust expert but &(*self) seems like a pointer for me and there is no pointer indexing in Rust as far as I know. So how does this indexing thing work? Is it just a compiler built-in thing?
Is it just a compiler built-in thing?
Yes. The source code comment also says that same. [T] is an unsized type and needs some extra rules anyway. For example, unsized types can't live on the stack (are pretty difficult to handle). But references to unsized types consist of a pointer and a size (specifically "something that completes the type").
Note, however, that the expression is evaluated like this: &((*self)[index]). This means that self (type &[T]) is dereferenced to be type [T] and then indexed. This returns a T, but we only want a reference to it, thus the &.

How does Julia recognize values as singleton types?

It is a cool feature of Julia that values can be used as types, at least as type parameters. For example, one can assert that arrays are of a particular dimensionality, such as x :: Array{Int,2}. My question is: how does Julia do that and how do users of Julia get access to that power? I assume that 2 is being converted to or interpreted as some sort of singleton type of 2. I am curious to know what function does that conversion. I tried to assert 2 :: Type{2} and isa(2, Type{2}), but that only asserts a singleton if 2 is replaced by an actual type.
You can not define your own imutables and use them as singleton types (yet).
Currently anything that makes static int valid_type_param(jl_value_t *v) defined in jltypes.c return true, can be used as a type parameter. There is a TODO to add more types, and you'll probably just need a compelling usecase to get help to change the behaviour.
Update:
See also the manual documentation on types: Both abstract and concrete types can be paramaterized by other types and by certain other values (currently integers, symbols, bools, and tuples thereof). Type parameters may be completely omitted when they do not need to be referenced or restricted.

Design 2 interactive modules in Ocaml

I would like to design 2 modules A and B which both have their own functions, for instance: A.compare: A.t -> A.t -> bool, B.compare: B.t -> B.t -> bool. The elements of A and B are convertible. So I would also need functions a_of_b : B.t -> A.t and b_of_a : A.t -> B.t. My question is where I should define these functions? inside the structure of A or the one of B or somewhere else?
Could anyone help?
Edit1: just amended some errors based on the first comment
This is a classic design problem. In OOP languages, it is hard to resolve this elegantly because a class encapsulates both a type definition and methods related to that type. Thus, as soon as you have a function such as a_of_b, which regards two types to an equal extent, there is no clear place for it.
OCaml correctly provides distinct language mechanisms for these distinct needs: type definitions are introduced with the keyword type, and related methods are collected together in a module. This gives you greater flexibility in designing your API, but does not solve the problem automatically.
One possibility is to define modules A and B, both with their respective types and compare functions. Then, the question remaining is where to put a_of_b and b_of_a. You could arbitrarily give preference to module A, and define the functions A.to_b and A.of_b. This is what the Standard Library did when it put to_list and of_list in Array. This lacks symmetry; there is no reason not to have put these functions in B instead.
Instead you could standardize on using of_ functions vs to_ functions. Let's say you prefer to_. Then you would define the functions A.to_b and B.to_a. The problem now is modules A and B are mutually dependent, which is only possible if you define them in the same file.
If you will have lots of functions that deal with values of type A.t and B.t, then it may be worth defining a module AB, and putting all these functions in there. If you will only need two, then an extra module is perhaps overkill.
On the other hand, if the total number of functions regarding A's and B's is small, you could create only the module AB, with type a, type b, and all related methods. However, this does not follow the OCaml community's convention of naming a type t within its own module, and it will be harder to apply the Set and Map functors to these types.
You probably mean A.compare: A.t -> A.t -> bool because types are in lower cases.
You can have a single module AB which contains both the type for A and the type for B.
You can have a single module AB containing both A & B as sub-modules.
You might also use recursive modules & functors.