/* * Copyright 2025 Magnus Madsen * * Use of this source code is governed by the Apache 2.0 license * that can be found in the LICENSE.md file. */pubmod Math.Shuffle {use Math.Shuffleimport java.util.{Random => JRandom}////// An effect used to shuffle collections.///pubeffShuffle {////// Returns a permutation of integers from 0 to `len - 1`.////// The permutation is represented as a vector where each position/// contains a unique integer in the range [0, len).///defpermutation(len: Int32): Vector[Int32] }////// Handles the `Shuffle` effect of the given function `f`.////// In other words, re-interprets the `Shuffle` effect using the `NonDet` effect.///pubdefhandle(f: a -> b \ ef): a -> b \ (ef - Shuffle) + NonDet = x ->run {f(x) } withhandlerShuffle {defpermutation(len, k) = {regionrc {letarr = Array.range(rc, 0, len);fisherYatesShuffle(arr);k(Array.toVector(arr)) } } }////// Runs the `Shuffle` effect of the given function `f`.////// In other words, re-interprets the `Shuffle` effect using the `NonDet` effect.///pubdefrunWithIO(f: Unit -> a \ ef): a \ (ef - Shuffle) + NonDet = handle(f)()////// Fisher-Yates shuffle algorithm for arrays.///deffisherYatesShuffle(arr: Array[Int32, r]): Unit \ { r, NonDet } = unsafeIOasr {letrnd = new JRandom();letlen = Array.length(arr);defloop(i) = {if (i>=len-1)()else {letj = i+rnd.nextInt(len-i);lettemp = Array.get(i, arr);Array.put(Array.get(j, arr), i, arr);Array.put(temp, j, arr);loop(i+1) } };loop(0) }}