Last active
February 3, 2025 21:31
-
-
Save qexat/fe059d1c7a055a261f9308e765efa24e to your computer and use it in GitHub Desktop.
a simple neige program
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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