What is the difference between min and minOf in Kotlin? - kotlin

In my legacy code I have this:
java.lang.Math.min(a, b)
I'd like to replace it with Kotlin equivalent, but I'm a little confused which one should I use. I found these two:
kotlin.math.min(a,b)
kotlin.comparisons.minOf(a,b)
As I noticed, both of them internally call Math.min. Is there any difference between them that I miss? Is one of them preferred for future use?

Kotlin kotlin.math.min(a,b) takes concrete types like Int, Double, Float, Long and compares them mathematically.
Kotlin kotlin.comparisons fun <T : Comparable<T>> minOf(a: T, b: T): T takes a generic type T, that extends the interface Comparable<T>. This can be used in collections to sort them, based on the implementation of Comparable on that class.
Which to use now?
As you see, kotlin.comparisons.minOf(a,b) is a more generic implementation than kotlin.math.min(a,b). If you are using number types it does not really matter which to use, as both are implemented with Math.min(a, b) as you already pointed out.

Related

Inheriting the methods in Kotlin classes?

I'm still quite new into Kotlin, and my current project is to write a tiny programming language using it.
I've progressed all the way through lexing and parsing, and got stuck when I'm trying to interpret it.
What I need is a class that inherit from both
A base class to tell Kotlin that the functions will definitely return an object in my programming language, instead of anything
A class for the methods to avoid writing dozens of (operator) functions that duplicate from Int, Float, etc.
I figured the base class can just be an interface to avoid multiple inheritance which Kotlin bans, like this
interface BaseObject {
val value: Any
}
class IntObject(override val value: Int): BaseObject, Int() {...}
class FloatObject(override val value: Float): BaseObject, Float() {...}
However the problem rises immediately. Int, Float, and many other classes are final and their constructor is private. This means inheriting them into my classes is not possible.
Is there any way that I can reuse the methods from Int, Float, etc. otherwise? I'm really not a fan of writing all the methods again. Alternatively, Do I have any other solutions in the implementation part, avoiding the problem completely?
Thanks in advance.
First off, what you probably want for your interface is something like this:
interface BaseObject<T> {
val value: T
}
which then means you can have your classes look like this:
class IntObject(override val value: Int) : BaseObject<Int>
class FloatObject(override val value: Float) : BaseObject<Float>
I'm not clear on how you want to use the objects where something like myObj.value + myOtherObj.value wouldn't work, but please let me know and I can update.

Relation between Arrow suspend functions and monad comprehension

I am new to Arrow and try to establish my mental model of how its effects system works; in particular, how it leverages Kotlin's suspend system. My very vague understanding is as follows; if would be great if someone could confirm, clarify, or correct it:
Because Kotlin does not support higher-kinded types, implementing applicatives and monads as type classes is cumbersome. Instead, arrow derives its monad functionality (bind and return) for all of Arrow's monadic types from the continuation primitive offered by Kotlin's suspend mechanism. Ist this correct? In particular, short-circuiting behavior (e.g., for nullable or either) is somehow implemented as a delimited continuation. I did not quite get which particular feature of Kotlin's suspend machinery comes into play here.
If the above is broadly correct, I have two follow-up questions: How should I contain the scope of non-IO monadic operations? Take a simple object construction and validation example:
suspend fun mkMessage(msgType: String, appRef: String, pId: String): Message? = nullable {
val type = MessageType.mkMessageType(msgType).bind()
val ref = ApplRefe.mkAppRef((appRef)).bind()
val id = Id.mkId(pId).bind()
Message(type, ref, id)
}
In Haskell's do-notation, this would be
mkMessage :: String -> String -> String -> Maybe Message
mkMessage msgType appRef pId = do
type <- mkMessageType msgType
ref <- mkAppRef appRef
id <- mkId pId
return (Message type ref id)
In both cases, the function returns the monad type (a nullable value, resp. Maybe). However, while I can use the pure function in Haskell anywhere I see fit, the suspend function in Kotlin can only be called from within a suspend function. In this way, a simple, non-IO monad comprehension in Arrow behaves like an IO monad that must be threaded throughout my code base; I suppose this results because the suspend mechanism was designed for actual IO operations. What is the recommended way to implement non-IO monad comprehensions in Arrow without making all functions into suspend functions? Or is this actually the way to go?
Second: If in addition to non-IO monads (nullable, reader, etc.), I want to have IO - say, reading in a file and parsing it - how would i combine these two effects? Is it correct to say that there would be multiple suspend scopes corresponding to the different monads involved, and I would need to somehow nest these scopes, like I would stack monad transformers in Haskell?
The two questions above probably mean that I am still lacking a mental model that bridges between the continuation-based implementation atop the Kotlin's suspend mechanism with the generic monad-as-typeclass implementation in Haskell.
schuster,
You're correct that Arrow uses the suspension feature from Kotlin to encode something like monad comphrensions.
To answer your first question:
Kotlin has suspend in the language (and Kotlin Std), by default suspend can only be called from other suspend code. However, the compiler also has a feature called RestrictsSuspension, this disallows for mixing suspend scopes and thus disallows the ablity to combine IO and Either for example. We expose a secondary DSL, either.eager which is encoded using RestrictsSuspension and it disallows calling foreign suspend functions.
This allows you to encode mkMessage :: String -> String -> String -> Maybe Message.
fun mkMessage(msgType: String, appRef: String, pId: String): Message? = nullable.eager {
val type = MessageType.mkMessageType(msgType).bind()
val ref = ApplRefe.mkAppRef((appRef)).bind()
val id = Id.mkId(pId).bind()
Message(type, ref, id)
}
To answer your second question:
IO as a data type is not needed in Kotlin, since suspend can implement all IO operations in a referential transparent way like it works in Haskell.
The compiler also makes a lot optimisations in the runtime, just like Haskell does for IO.
So the signature suspend fun example(): Either<Error, Value> is the equivalent of EitherT IO Error Value in Haskell.
The IO operations are however not implemented in the Kotlin Std, but in a library KotlinX Coroutines, and Arrow Fx Coroutines also offers some data types and higher-level operations such as parTraverse defined on top of KotlinX Coroutines.
It's slightly different than in Haskell, since we can mix effects instead of stacking them with monad transformers. This means that we can call IO operations from within Either operations. This is due to special functionality, and optimisations the compiler can make in the suspension system. This blog explains how that optimisation works, and why it's so powerful. https://nomisrev.github.io/inline-and-suspend/
Here is also some more background on Continuations, and tagless encodings in Kotlin. https://nomisrev.github.io/continuation-monad-in-kotlin/
I hope that fully answers your question.
I don't think I can answer everything you asked, but I'll do my best for the parts that I do know how to answer.
What is the recommended way to implement non-IO monad comprehensions in Arrow without making all functions into suspend functions? Or is this actually the way to go?
you can use nullable.eager and either.eager respectively for pure code. Using nullable/either (without .eager) allows you to call suspend functions inside. Using eager means you can only call non-suspend functions. (not all effectual functions in kotlin are marked suspend)
Second: If in addition to non-IO monads (nullable, reader, etc.), I want to have IO - say, reading in a file and parsing it - how would i combine these two effects? Is it correct to say that there would be multiple suspend scopes corresponding to the different monads involved, and I would need to somehow nest these scopes, like I would stack monad transformers in Haskell?
You can use extension functions to emulate Reader. For example:
suspend fun <R> R.doSomething(i: Int): Either<Error, String> = TODO()
combines Reader + IO + Either. You can find a bigger example here from Simon, an Arrow maintainer.

how to read kotlin type annotations

I'm coming to kotlin after working in mostly dynamically typed languages for years, so I get a lot of what I'm seeing, but I'm still tripping up a bit over reading some of the type annotations.
Most of them make sense (I've written some C++ and typescript so I'm not wholey familiar with more strictly type languages). so stuff like annotating the parameters and return types for functions, variable declaration, stuff like that makes sense.
What I'm having trouble with is the more complex annotations like looking at this explanation of the fold method when talking about higher order functions:
fun <T, R> Collection<T>.fold(
initial: R,
combine: (acc: R, nextElement: T) -> R
): R {
var accumulator: R = initial
for (element: T in this) {
accumulator = combine(accumulator, element)
}
return accumulator
}
I get that:
the Collection refers to an arbitrary collection with elements that are of type T
the fold method call takes an value of type R named initial as the first argument and a callable function labeled combine as the second argument
the callable function will be called for each element of the collection with an accumulator of type R labeled acc and the next element of the collection of type T (since it's a collection of Ts) labeled nextElement
The callable function will return a type R in the end
The fold method will return a type R in the end
And I can use it like this:
val greetings = listOf("hey", "hi", "yo", "what's up")
val personalized = greetings.fold("", { carry, current -> "${carry}\n$current, Chris." })
println(personalized)
That all makes sense, but what does the <T, R> between the fun and the Collection mean? What is that part called? (It's hard to search for an explanation when you don't know what the thing you're looking for is called :P)
And more importantly, is there a section of the documentation that specifically talks about how to read these annotations or what each are called? I've been looking through the docs and searching in general for an explanation of how to read the type annotations and I can't find anything.
It feels like a silly question, but to the uninitiated it's kind of daunting and the docs are written as if you already understand that part of the language.
As Alexey already said, these names between angled brackets after the fun keyword are called "type parameters". They are used to declare generic functions.
the Collection refers to an arbitrary collection with elements that are of type T
Here you can see that Collection and T play different roles: Collection is a well-known defined type that you are referencing, while T is just a name that you arbitrarily choose for the definition of this function.
We want the compiler to check that Collection is a type that is defined and imported, and if you make a typo there will be a compile error.
On the other hand, we don't want that for T and R, so it is necessary to mention them in a special syntactic place so that the compiler knows you're just making up arbitrary names for the sake of the function definition.
It is nice to draw a parallel between the type parameters and the method arguments. The method arguments are also arbitrary names that you define in the signature and use in the function body, as opposed to class members like properties, which you can access without declaring them as arguments.
Just like the values of the arguments are passed when you call a method, and can be different for each different invocation, the "values" of the type parameters are also given at the call site, and can be different for each invocation (they are often inferred, though, so you don't see them).
Note that the "value" of a type parameter is a type (e.g. String), not a value in the usual sense like the string "abc". You can actually specify these types explicitly on the call site if you want:
listOf(1, 2, 3).fold<Int, Int>(42) { acc, e -> acc + e }
The syntax on the call site is similar to the declaration site, it uses <>, except that it's written after the function name.
In general, these types are easily inferred by the compiler using the argument types or the return type in the context of the call site, that's why it's often unnecessary to explicitly specify them.
Difference with generics at the class level
It may seem weird that the methods in the interface List don't need to declare such type parameters, despite the fact that they use generic types:
interface MutableList<T> {
fun add(element: T): Boolean {
//....
}
}
This is because T is already "well-defined" when using it for the method declaration: it was already defined as a type parameter for the List interface itself. The mechanism is the same, but the difference is the scope of the definition: class-level type parameters are defined by the instance of the class (you can create a List<Int> or a List<String>, and this is chosen when you create your instance), while function type parameters are defined by each call to the function.
You can even combine both:
interface List<T> {
fun <R> map(transform: (T) -> R): List<R> {
//...
}
}
Here T will be determined by the list instance on which you call map, but R can be different for each call to map even on the same list instance.
<T, R> are the type parameters. Since you are familiar with C++, it's like
template <typename T, typename R>
It just happens to be placed after the fun keyword in Kotlin (and after the type name when declaring a generic class/interface/type alias) instead of before the function definition.

Kotlin benifits of writing helper/util methods without wrapping in class

There are can be two ways of writing helper method in Kotlin
First is
object Helper {
fun doSomething(a: Any, b: Any): Any {
// Do some businesss logic and return result
}
}
Or simply writing this
fun doSomething(a: Any, b: Any): Any {
// Do some businesss logic and return result
}
inside a Helper.kt class.
So my question is in terms of performance and maintainability which is better and why?
In general, your first choice should be top-level functions. If a function has a clear "primary" argument, you can make it even more idiomatic by extracting it as the receiver of an extension function.
The object is nothing more than a holder of the namespace of its member functions. If you find that you have several groups of functions that you want to categorize, you can create several objects for them so you can qualify the calls with the object's name. There's little beyond this going in their favor in this role.
object as a language feature makes a lot more sense when it implements a well-known interface.
There's a third and arguably more idiomatic way: extension functions.
fun Int.add(b: Int): Int = this + b
And to use it:
val x = 1
val y = x.add(3) // 4
val z = 1.add(3) // 4
In terms of maintainability, I find extension functions just as easy to maintain as top-level functions or helper classes. I'm not a big fan of helper classes because they end up acquiring a lot of cruft over time (things people swear we'll reuse but never do, oddball variants of what we already have for special use cases, etc).
In terms of performance, these are all going to resolve more or less the same way - statically. The Kotlin compiler is effectively going to compile all of these down to the same java code - a class with a static method.

generics compilation error in kotlin [duplicate]

I have a generically typed class Builder<T> that takes a constructor argument Class<T> so I can keep the type around. This is a class that I use a lot in java code so I don't want to change the signature.
When I try to use the constructor like this:
Builder<List<Number>>(List<Number>::class)
I get an error: "Only classes are allowed on the left hand side of a class literal"
Any way to resolve this?
I can't change the constructor for Builder, too many java classes rely upon it.
I understand the whole type erasure issue, I really just want to make the compiler happy.
Due to generic type erasure List class has a single implementation for all its generic instantiations. You can only get a class corresponding to List<*> type, and thus create only Builder<List<*>>.
That builder instance is suitable for building a list of something. And again due to type erasure what that something is you can decide by yourself with the help of unchecked casts:
Builder(List::class.java) as Builder<List<Number>>
Builder(List::class.java as Class<List<Number>>)
Another approach is to create inline reified helper function:
inline fun <reified T : Any> Builder() = Builder(T::class.java)
and use it the following way:
Builder<List<Number>>()
The solution is to use reified generics in couple with super class tokens.
Please refer to this question for the method explained. Constructors in Kotlin don't support reified generics, but you can use TypeReference described there to write a builder factory function which will retain actual generic parameters at runtime:
inline <reified T: Any> fun builder(): Builder<T> {
val type = object : TypeReference<T>() {}.type
return Builder(type)
}
Then inside Builder you can check if type is ParameterizedType, and if it is, type.actualTypeArguments will contain the actual generic parameters.
For example, builder<List<Number>>() will retain the information about Number at runtime.
The limitation of this approach is that you cannot use non-reified generic as a reified type parameter because the type must be known at compile-time.