Skip to content

Instantly share code, notes, and snippets.

@qexat
Last active February 3, 2025 21:31
Show Gist options
  • Save qexat/fe059d1c7a055a261f9308e765efa24e to your computer and use it in GitHub Desktop.
Save qexat/fe059d1c7a055a261f9308e765efa24e to your computer and use it in GitHub Desktop.
a simple neige program
#!/usr/bin/env -S neige run
extend Nat with module
# This version does not care about a leading zero
let parse_decimal_digits : String -> List Nat =
let tailrec string acc =
match string with
| "" -> acc
| ('0' .. '9' as first) :: rest ->
let digit = Char.code_point_of first - Char.digit_offset in
tailrec rest (acc ++ digit)
end
in
fun string -> tailrec string []
let from_parsing (string : String) : Option Nat =
match string with
| "0" -> Some O
# TODO: support non-decimal bases
| '0' :: _ -> None
| _ ->
parse_decimal_digits string
|> List.reverse
|> List.enum_map (fun index digit -> digit * 10^index)
|> Some
let show : Nat -> String =
let tailrec n acc =
match n with
| 0 -> acc
| _ ->
let (rest, last) = divmod n 10 in
# We can't deal with Char.from_code_point Option return value
# because we know it won't fail - so we have to use the version
# that produces � (U+FFFD) for invalid code points
let last_char = Char.from_code_point_total (last + Char.digit_offset) in
tailrec rest (last_char ++ acc)
end
in fun n ->
match n with
| 0 -> "0"
| _ -> tailrec n ""
end
end
abstract type Parsable as P
with module
val from_parsing : String -> Option P
end
abstract type Showable as S
with module
val show : S -> String
end
let input : (from : Channel Input) -> Sort (?T <: Parsable) -> Option ?T =
fun %from(channel) Type ->
let raw_input = (Channel Input).read_line channel in
Type.from_parsing raw_input
let output {T <: Showable} : (to : Channel Output) -> T -> Unit =
fun %to(channel) value ->
(Channel Input).write_line channel (T.show value)
let factorial 0 = 1
and factorial (S n' as n) = n * factorial n'
let _ =
let* n = input %from(stdin) Nat in
output %to(stdout) (factorial n) in
None
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment