Skip to content

Instantly share code, notes, and snippets.

@maedoc
Last active October 1, 2021 19:23
Show Gist options
  • Save maedoc/cab49e0916c49ff1dd14aaacb8fd480b to your computer and use it in GitHub Desktop.
Save maedoc/cab49e0916c49ff1dd14aaacb8fd480b to your computer and use it in GitHub Desktop.
Polymorphic arithmetic in Futhark
-- was not clear to me from the user guide how this is supposed to work
-- when in fact it's straightforward
-- put the needed arithmetic ops in an "interface" / "concept"
module type arith = {
type t
val i32 : i32 -> t
val * : t -> t -> t
}
-- put the functions that should be "templated"
-- in their own module parametrized by the above interface:
module algo (N:arith) = {
open N -- this may bring more names into scope than we want
let f (x:t) (y:[]t): []t = map (\y -> x * y * (i32 1)) y
}
-- if the functions use multiples types in arithmetic e.g. indexing
-- then it may be easier to keep the module parameter explicit:
module algo2 (R:arith) = {
let f [n] (x:[n]R.t): [n]R.t = iota (n - 1)
|> map (\i -> (x[i+1] R.* x[i]))
|> ([R.i32 0]++) :> [n]R.t
}
-- dense math can use syntax R.(x + y * z) to keep it readable
-- maybe define a custom type & arithmetic
module ratio = {
type t = (i32, i32)
let i32 (i:i32): t = (i, 1)
let (*) (l:t) (r:t) = (l.0 * l.1, l.0 * l.1)
}
-- instantiate the algorithms for specific implementations
module u1 = algo { open f64 }
module u2 = algo ratio
-- profit
let main = (
u1.f 1f64 [0f64, 1f64],
u2.f (1i32,2i32) [(2i32,2i32), (4i32,-1i32)]
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment