// // Cat Standard Library // by Christopher Diggins // http://www.cdiggins.com // this file is public domain //============================================================================= // Basic shuffling operators define swapd : ('a 'b 'c -> 'b 'a 'c) { [swap] dip } define swapdd : ('a 'b 'c 'd -> 'b 'a 'c 'd) { [swapd] dip } define dupd : ('a 'b -> 'a 'a 'b) { [dup] dip } define dupdd : ('a 'b 'c -> 'a 'a 'b 'c) { [dupd] dip } define popd : ('a 'b -> 'b) { [pop] dip } define popdd : ('a 'b 'c -> 'b 'c) { [popd] dip } define dup2 : ('a -> 'a 'a 'a ) { dup dup } define pop2 : ('a 'b -> ) { pop pop } define dup3 : ('a -> 'a 'a 'a 'a ) { dup dup dup dup } define pop3 : ('a 'b 'c -> ) { pop pop pop pop } define dup4 : ('a -> 'a 'a 'a 'a 'a ) { dup dup dup dup } define pop4 : ('a 'b 'c 'd -> ) { pop pop pop pop } define nip : ('a 'b -> 'b) { popd } define over : ('a 'b -> 'a 'b 'a) { dupd swap } define under : ('a 'b -> 'b 'a 'b) { dup swapd } define flip : ('a 'b 'c -> 'c 'b 'a) { swapd swap swapd } define bury : ('a 'b 'c -> 'c 'a 'b) { swap swapd } define dig : ('a 'b 'c -> 'b 'c 'a) { swapd swap } define peek : ('a 'b 'c -> 'a 'b 'c 'a) { dupdd dig } define poke : ('a 'b 'c -> 'c 'b) { popdd swap } //============================================================================== // Argument list manipulation // Declares an empty argument list define arg_list : ( -> list) { nil } // Argument accessors define arg0 : (list -> var list) { 0 nth swap } define arg1 : (list -> var list) { 1 nth swap } define arg2 : (list -> var list) { 2 nth swap } define arg3 : (list -> var list) { 3 nth swap } define arg4 : (list -> var list) { 4 nth swap } define arg5 : (list -> var list) { 5 nth swap } define arg6 : (list -> var list) { 6 nth swap } define arg7 : (list -> var list) { 7 nth swap } define arg8 : (list -> var list) { 8 nth swap } define arg9 : (list -> var list) { 9 nth swap } // Used for converting from quotations inside of functions with named // arguments to point-free form by prepending the argument list. define embed_args { [dup quote] dip compose swap } //============================================================================= // Common predicates. // Predicate usually have the form: 'A -> 'A bool define eqz : (int -> int bool) { dup 0 eq } define neqz : (int -> int bool) { eqz not } define gtz : (int -> int bool) { dup 0 gt } define gteqz : (int -> int bool) { dup 0 gteq } define ltz : (int -> int bool) { dup 0 lt } define lteqz : (int -> int bool) { dup 0 lteq } // Not really a predicate, but used to generate predicate define modn : (int int -> int bool) { dupd mod 0 eq } define even : (int -> int bool) { 2 modn } define odd : (int -> int bool) { dup inc mod 0 eq } //============================================================================= // predicate generation functions define ltf : ('a -> ('a -> 'a bool)) { [dupd lt] curry } define lteqf : ('a -> ('a -> 'a bool)) { [dupd lteq] curry } define gtf : ('a -> ('a -> 'a bool)) { [dupd gt] curry } define gteqf : ('a -> ('a -> 'a bool)) { [dupd gteq] curry } define eqf : ('a -> ('a -> 'a bool)) { [dupd eq] curry } define neqf : ('a -> ('a -> 'a bool)) { [dupd neq] curry } define modnf : (int int -> (int -> int bool)) { [dupd modn] curry } //============================================================================= // Additional mathematical definitions define inc : (int -> int) { 1 add } define dec : (int -> int) { 1 sub } //============================================================================= // Mathematical symbols define + { add } define - { sub } define * { mul } define % { mod } define / { div } define < { lt } define > { gt } define <= { lteq } define >= { gteq } define == { eq } define != { neq } //============================================================================= // Additional combinators // Sometime called "slip" define swip : ('A ('A -> 'B) 'c -> 'B 'c) { swap dip } // Sometimes called "sip" define keep : ('A 'b ('A 'b -> 'C) -> 'C 'b) { dupd dip } define sweep : ('A ('A 'b -> 'C) 'b -> 'C 'b) { swap keep } define dip2 : ('A 'b 'c ('A -> 'D) -> 'D 'b 'c) { swap [dip] swip } define dip3 : ('A 'b 'c 'd ('A -> 'E) -> 'E 'b 'c 'd) { swap [dip2] swip } define dip4 : ('A 'b 'c 'd 'e ('A -> 'F) -> 'F 'b 'c 'd 'e) { swap [dip3] swip } //============================================================================= // List operators define ( { nil } define , { cons } define ) { cons } define swons : (var list -> list) { swap cons } define uncons : (list -> list var) { head [tail nip] dip } define uncons2 : (list -> list var var) { uncons [uncons] dip } define uncons3 : (list -> list var var var) { uncons [uncons2] dip } define uncons4 : (list -> list var var var var) { uncons [uncons3] dip } define first2 : (list -> var var) { uncons [first] dip } define first3 : (list -> var var var) { uncons [first2] dip } define first4 : (list -> var var var var) { uncons [first3] dip } define range : (int int -> list) { ltf [inc] gen } define n : (int -> list) { 0 swap range } define flatten : (list -> list) { nil [cat] foldl } // Returns true iff any value satisfies the condition // Could be optimized define any : (list ('a -> bool) -> bool) { dupd [or] compose false swap foldl } // Returns true iff all values satisfy the condition // Could be optimized define all : (list ('a -> bool) -> bool) { dupd [and] compose true swap foldl } //============================================================================= // Infinite list generators define naturals : ( -> list) { 0 [true] [inc] gen } define odds : ( -> list) { 1 [true] [inc] gen } define evens : ( -> list) { 0 [true] [inc] gen } define negatives : ( -> list) { 1 neg [true] [dec] gen } //============================================================================= // Function manipulation operators define curry : ('a ('B 'a -> 'C) -> ('B -> 'C)) { [quote] dip compose } define curry2 : ('a 'b ('C 'a 'b -> 'D) -> ('C -> 'D)) { curry curry } define curry3 : ('a 'b 'c ('D 'a 'b 'c -> 'E) -> ('D -> 'E)) { curry curry curry } define curry4 : ('a 'b 'c 'd ('E 'a 'b 'c 'd -> 'F) -> ('E -> 'F)) { curry curry curry curry } define curry5 : ('a 'b 'c 'd 'e ('F 'a 'b 'c 'd 'e -> 'G) -> ('F -> 'G)) { curry curry curry curry curry } define rcurry : (('B 'a -> 'C) 'a -> ('B -> 'C)) { quote swap compose } //============================================================================== // Looping constructions define repeat : ('A ('A -> 'A) int -> 'A) { swap [swip dec] curry [neqz] while pop } // reverse for loop define rfor : ('A ('A int -> 'A) int -> 'A) { swap [sweep dec] curry [neqz] while pop } //============================================================================== // Vector functions define sum : (list -> var) { 0 [+] foldl } //============================================================================== // Hash helper functions // Gets a value from a hash_list. If it doesn't exist then uses the default define hash_safe_get : (hash_list key=var default=var -> hash_list var) { [[hash_contains] keep] dip // => hash_list bool key default quote // => hash_list bool key [default] [[hash_get] curry] dip // => hash_list bool [key hash_get] [default] if // => hash_list result } // Adds an element as unit list to a hash_list if it doesn't exist, // otherwise chain it to the current list item. define hash_add_chain : (hash_list key=var value=var -> hash_list) { [[nil hash_safe_get] keep] dip // => hash_list curr key value swapd cons // => hash_list key list(curr, value) hash_set // => hash_list } define list_to_hash : (list -> hash_list) { hash_list [uncons swap hash_add_chain] foldl } // performs an inner self-join on a list of lists based the first item. define self_join : (list -> list) { list_to_hash hash_to_list }