diff --git a/src/curry.rs b/src/curry.rs
new file mode 100644
index 0000000..7ee04d8
--- /dev/null
+++ b/src/curry.rs
@@ -0,0 +1,63 @@
+use crate::term::*;
+
+//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
+
+impl TypeTerm {
+ /// transform term to have at max 2 entries in Application list
+ pub fn curry(mut self) -> TypeTerm {
+ match self {
+ TypeTerm::App(args) => {
+ if args.len() >= 2 {
+ let mut old_args = args.into_iter();
+ let mut new_args = vec![
+ old_args.next().unwrap(),
+ old_args.next().unwrap()
+ ];
+
+ for x in old_args {
+ new_args = vec![
+ TypeTerm::App(new_args),
+ x
+ ];
+ }
+
+ TypeTerm::App(new_args)
+ } else {
+ TypeTerm::App(args)
+ }
+ }
+
+ TypeTerm::Ladder(rungs) => {
+ TypeTerm::Ladder(rungs.into_iter().map(|r| r.curry()).collect())
+ }
+
+ _ => self
+ }
+ }
+
+ /// summarize all curried applications into one vec
+ pub fn decurry(mut self) -> Self {
+ match self {
+ TypeTerm::App(mut args) => {
+ if args.len() > 0 {
+ let mut a0 = args.remove(0).decurry();
+ match a0 {
+ TypeTerm::App(sub_args) => {
+ for (i,x) in sub_args.into_iter().enumerate() {
+ args.insert(i, x);
+ }
+ }
+ other => { args.insert(0, other); }
+ }
+ }
+ TypeTerm::App(args)
+ }
+ TypeTerm::Ladder(args) => {
+ TypeTerm::Ladder(args.into_iter().map(|a| a.decurry()).collect())
+ }
+ _ => self
+ }
+ }
+}
+
+//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
diff --git a/src/lib.rs b/src/lib.rs
index 1f1ffcb..0319a0c 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -4,6 +4,7 @@ pub mod dict;
pub mod term;
pub mod lexer;
pub mod parser;
+pub mod curry;
#[cfg(test)]
mod test;
diff --git a/src/test/curry.rs b/src/test/curry.rs
index 1e6b676..8ad1cdf 100644
--- a/src/test/curry.rs
+++ b/src/test/curry.rs
@@ -1,6 +1,58 @@
+use {
+ crate::{term::*, dict::*, parser::*},
+ std::str::FromStr
+};
+
+//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\
#[test]
fn test_curry() {
- // todo
+ assert_eq!(
+ TypeTerm::from_str("").unwrap().curry(),
+ TypeTerm::from_str("< C>").unwrap()
+ );
+ assert_eq!(
+ TypeTerm::from_str("").unwrap().curry(),
+ TypeTerm::from_str("<< C> D>").unwrap()
+ );
+ assert_eq!(
+ TypeTerm::from_str("").unwrap().curry(),
+ TypeTerm::from_str("<<<<<<<<< C> D> E> F> G> H> I> J> K>").unwrap()
+ );
+
+ assert_eq!(
+ TypeTerm::from_str("").unwrap().curry(),
+ TypeTerm::from_str("< C>").unwrap()
+ );
+ assert_eq!(
+ TypeTerm::from_str(" ~ K").unwrap().curry(),
+ TypeTerm::from_str("< C~Y~Z > ~ K").unwrap()
+ );
}
+#[test]
+fn test_decurry() {
+ assert_eq!(
+ TypeTerm::from_str("< C>").unwrap().decurry(),
+ TypeTerm::from_str("").unwrap()
+ );
+ assert_eq!(
+ TypeTerm::from_str("<< C> D>").unwrap().decurry(),
+ TypeTerm::from_str("").unwrap(),
+ );
+ assert_eq!(
+ TypeTerm::from_str("<<<<<<<<< C> D> E> F> G> H> I> J> K>").unwrap().decurry(),
+ TypeTerm::from_str("").unwrap()
+ );
+
+ assert_eq!(
+ TypeTerm::from_str("< C>").unwrap().decurry(),
+ TypeTerm::from_str("").unwrap()
+ );
+ assert_eq!(
+ TypeTerm::from_str("< C~Y>~K").unwrap().decurry(),
+ TypeTerm::from_str(" ~K").unwrap()
+ );
+}
+
+//<<<<>>>><<>><><<>><<<*>>><<>><><<>><<<<>>>>\\