The Hash
typeclass abstracts the ability to compute the hash of any object.
It can be considered the typeclass equivalent of Java’s Object#hashcode
and Kotlin’s Any#hashCode
.
A hash function is a mapping of arbitrary data (F
) to an output set of fixed size (Int
). The result, a hash value, is most commonly used in collections like HashTable as a lookup value.
import arrow.core.extensions.*
fun main(args: Array<String>) {
//sampleStart
// Enable the extension functions inside Hash using run
val result = String.hash().run { "1".hash() }
//sampleEnd
println(result)
}
Computes a hash of an instance of F
.
fun F.hash(): Int
import arrow.core.extensions.*
fun main(args: Array<String>) {
//sampleStart
// Enable the extension functions inside Hash using run
val result = String.hash().run { "MyString".hash() }
//sampleEnd
println(result)
}
Arrow provides HashLaws
in the form of test cases for internal verification of lawful instances and third party apps creating their own Hash
instances.
Hash
instancesHash contains a special instance that delegates to Kotlin’s Any?.hashCode()
function in all cases. This may be sufficient for most use cases, but will fail for data types that contain functions, typeclasses, or non-data classes.
It also might make more sense to provide your own instance in some cases; for example, when there is already a unique property on an object.
Hash has a constructor to create a Hash
instance from any function (F) -> Int
.
import arrow.typeclasses.Hash
data class User(val id: String, val name: String)
val user = User("MyId", "MyName")
fun main(args: Array<String>) {
//sampleStart
// This is fine
val result = Hash.any().run { user.hash() }
//sampleEnd
println(result)
}
import arrow.typeclasses.Hash
data class User(val id: String, val name: String)
val user = User("MyId", "MyName")
fun main(args: Array<String>) {
//sampleStart
// This might be better because id usually is a unique value in itself
val userHash = Hash<User> { u -> u.id.hashCode() }
val result = userHash.run { user.hash() }
//sampleEnd
println(result)
}
import arrow.core.*
import arrow.typeclasses.Hash
fun main(args: Array<String>) {
//sampleStart
// This will return false because it's not evaluated for hashing
val result = Hash.any().run { Eval.later { 1 }.hash() == Eval.later { 1 }.hash() }
//sampleEnd
println(result)
}
import arrow.typeclasses.Hash
fun main(args: Array<String>) {
//sampleStart
// using invoke constructor
val stringHash = Hash<String> { a -> a.hashCode() }
val result = stringHash.run { "MyString".hash() }
//sampleEnd
println(result)
}
See Deriving and creating custom typeclass to provide your own Hash
instances for custom datatypes.
Do you like Arrow?
✖