Nice TWiki > Doc > CodeExamples > HaskellPreludeExample TWiki webs:
Dev | Doc | Main | TWiki | Sandbox
Doc . { Changes | Index | Search | Go }
This is a large portion of the Haskell prelude, at least those parts which can be translated sensibly into Nice. This example is under construction.

Still needs tests, and some standardization of parameter order, return types, etc. Also, many of these should be methods, not functions.

Updated!The whole example compiles now. Uncommented many functions that wouldn't compile earlier due to my misunderstandings of the old tuple type syntax, the old "return must be the last statement in an anonymous function" problem, and other such difficulties.

Added some doc comments though many more are needed, and changed argument orders in some functions to be more natural in Nice. Made some functions into methods, specialized for Sequence and for LazyVector.

-- BrynKeller - 29 Jul 2002

//import collections.LazyVector;

/**
 * Boolean not operator.
 */
<Any T> boolean not(boolean b) = !b;

/**
 * 
 */
<Any T, Any U> U maybe(U defaultValue, T->U xform, ?T maybeItem) {
  if (maybeItem == null) {
    return defaultValue;
  } else {
    return xform(cast(maybeItem));
  }
}

/**
 * Returns the first element of a 2-tuple.
 */
<Any T, Any U> T fst((T,U) tup) {
  (T t, U u) = tup;
  return t;
}

/**
 * Returns the second element of a 2-tuple.
 */
<Any T, Any U> U snd((T, U) tup) {
  (T t, U u) = tup;
  return u;
}

/**
 * Returns the first element of a 3-tuple.
 */
<Any T, Any U, Any V> T fst3((T, U, V) tup) {
  (T t, U u, V v) = tup;
  return t;
}

/**
 * Returns the second element of a 3-tuple.
 */
<Any T, Any U, Any V> U snd3((T, U, V) tup) {
  (T t, U u, V v) = tup;
  return u;
}

/**
 * Returns the third element of a 3-tuple.
 */
<Any T, Any U, Any V> V thrd((T, U, V) tup) {
  (T t, U u, V v) = tup;
  return v;
}

/**
 * Given a function <tt>func</tt>, which takes two arguments, return a function
 * which takes one argument, and returns another function which takes an argument
 * and returns the final result. An example is probably clearer:
 *
 *  * var (int,int)->int addInts = (int x, int y) => {
 *                         return x + y;
 *                     };
 * println(addInts(5,6));
 * 
 * var int->int->int curriedAddInts = curry(addInts);
 * var addFive = curriedAddInts(5);
 * println(addFive(6));
 * </pre>
 * 
 * prints "11" twice.
 *
 * @see uncurry
 * @see flip
 */
<Any T, Any U, Any V> T->U->V curry((T,U)->V func) =  T parm1 => U parm2 => func(parm1, parm2); 

/**
 * Given a curried function func (see the <tt>curry</tt> function), return a function
 * which takes two arguments, the opposite of <tt>curry</tt>.
 *
 * @see curry
 * @see flip
 */
<Any T, Any U, Any V> (T,U)->V uncurry(T->U->V func) = (T parm1, U parm2) => func(parm1)(parm2);

//<Any T> T id(T t) = t;

/**
 * Function composition. Given functions f2 and f1, return a function which takes the same
 * argument f1 did, and returns the same thing f2 did. That is, <tt>compose(f2, f1)</tt>
 * returns a function which is equivalent to <tt>f2(f1(x))</tt>.
 */
<Any T, Any U, Any V> T->V compose(U->V f2, T->U f1) = T parm => f2(f1(parm));

/**
 * Reverses argument order for a curried function.
 */
<Any T, Any U, Any V> U->T->V flip(T->U->V func) = U parm2 => T parm1 => func(parm1)(parm2); 

/**
 * Reverses argument order for a normal function with two parameters.
 */
<Any T, Any U, Any V> (U, T)->V flipT((T,U)->V func) = (U parm2, T parm1) => func(parm1, parm2); 

/**
 * Repeatedly applies <tt>xform</tt> to its own result, using <tt>item</tt> as a starting
 * value, until <tt>check</tt> returns true, then returns the last result from <tt>xform</tt>.
 */
<Any T> T until(T->boolean check, T->T xform, T item) {
  while(!check(item)) {
    item = xform(item);
  }
  return item;
}

/**
 * Throw a runtime exception.
 * @param msg=Error message
 *
 */
void exception(String msg) {
  throw new RuntimeException(msg);
}

<Any A, Any B> Sequence<A> scanLeft(Sequence<B> seq, (A,B)->A func, A start);

scanLeft<A,B>(seq@Sequence, func, start) {
  Vector<A> vec = makeVector(size(seq));
  vec.add(start);
  A last = start;
  B next;
  for(int i = 0; i < size(seq); i++) {
    next = seq[i];
    last = func(last, next);
    vec.add(last);
  }
  return vec;
}

scanLeft<A,B>(seq@LazyVector, func, start) {  
  int counter = 0;
  A last = start;
  return makeLV(()=>{
    last = func(last, seq[counter]);
    counter++;
    return start;
  });
}

<Any A> Sequence<A> scanLeft1(Sequence<A> seq, (A,A)->A func );

scanLeft1<A>(seq@Sequence, func) {
  Vector<A> vec = makeVector(size(seq));  
  vec.add(seq[0]);
  A last = seq[0];
  A next;
  for(int i = 1; i < size(seq); i++) {
    next = seq[i];
    last = func(last, next);
    vec.add(last);
  }
  return vec;
}

scanLeft1<A>(seq@LazyVector, func) {
  int counter = 0;
  A start = cast(null); //We will definitely initialize this variable before
                         //actually using it, but not sure how to prove this to
                         //the compiler.
  return makeLV(()=> {    
    if (counter == 0) {
      start = seq[0];
      counter++;
    }
    start = func(start, seq[counter]);
    counter++;
    return start;
  });
}

<Any A> A foldLeft1(Sequence<A> seq, (A, A)->A func) {
  A result = seq[0];
  //Avoid asking for size() because it might (like for linked lists)
  //be expensive to do so, and we don't actually need it for a left 
  //fold.
  try {
    for(int i = 1;; i++) {
      result = func(seq[i], result);
    }
  } catch (ArrayIndexOutOfBoundsException e) { 
    //Walked off end of seq, not an error
  }  
  return result;
}

<Any A, Any B> B foldRight((A, B)->B func, B start, Sequence<A> seq) {
  B result = start;
  for(int i = size(seq) - 1; i >= 0; i--) {
    result = func(seq[i], start);
  }
  return result;
}

<Any A> A foldRight1(Sequence<A> seq, (A, A)->A func) {
  A result = seq[size(seq) - 1];
  for(int i = size(seq) - 2; i >= 0; i--) {
    result = func(seq[i], result);
  }
  return result;
}

<Any A, Any B> Sequence<B> scanRight(Sequence<A> seq, (A,B)->B func, B start) {
  Vector<B> vec = makeVector(size(seq));
  vec.add(start);
  B last = start;
  for(int i = size(seq) - 1; i >= 0; i--) {
    vec.add(func(seq[i], last));
  } 
  return vec;
}

<Any A> Sequence<A> scanRight1(Sequence<A> seq, (A,A)->A func, A start) {
  Vector<A> vec = makeVector(size(seq));
  vec.add(start);
  A last = seq[size(seq) - 1];
  for(int i = size(seq) - 2; i >= 0; i--) {
    vec.add(func(seq[i], last));
  } 
  return vec;
}

<Any A> LazyVector<A> iterate(A->A func, A start) {
  LazyVector<A> vec = makeLV(() => {
    start = func(start);
    return start;
  });
  vec.elements[0] = start;
  vec.length = 1;
  return vec;
}

<Any A> LazyVector<A> repeat(A item) = makeLV(() => item);

<Any A> Sequence<A> replicate(int number, A item) = repeat(item).take(number);

<Any A> LazyVector<A> cycle(Sequence<A> seq) {
  int currentIndex = 0;
  return makeLV(() => {
    if (size(seq) <= currentIndex) {
      currentIndex = 0;
    }
    A item = seq[currentIndex];
    currentIndex++;
    return item;
  });
}  

<Any A> Sequence<A> take(Sequence<A> seq, int number);

take<A>(seq@Sequence, number) {
  if (number <= 0) {
    return makeVector(0);
  } else {
    Vector<A> vec = makeVector(number);
    int maxLen = min(number, size(seq));
    for(int i = 0; i < maxLen; i++) {
      vec.add(seq[i]);
    }
    return vec;
  }
}

take<A>(seq@LazyVector, number) = makeLV(()=> seq[number++]);

<Any A> Sequence<A> drop(Sequence<A> seq, int number);
drop<A>(seq@Sequence, number) {
  if (number <= 0) {
    return new Vector(elements: toArray(seq), length: seq.size());
  }
  if (seq.size() < number) {
    return makeVector(0);
  }
  Vector<A> vec = makeVector(seq.size() - number);
  while(true) {
    try {
      vec.add(seq[number]);
      number++;
    } catch (Exception e) {
      break;
    }
  }
  return vec;
}

drop<A>(seq@LazyVector, number) = makeLV(() => seq[number++]);

<Any A> (Sequence<A>, Sequence<A>) splitAt(Sequence<A> seq, int index);

splitAt<A>(seq@Sequence, index) {
  Vector<A> first = makeVector(index);
  Vector<A> second = makeVector(10);
  for(int i = 0;; i++) {
    try {
      if (i < index)
   first.add(seq[i]);
      else
   second.add(seq[i]);
    } catch (Exception e) {
      //Nothing...
    }
  }
  return (first, second);
}

<Any T> Sequence<T> takeWhile(Sequence<T> seq, T->boolean test) {
  Vector<T> vec = makeVector(10);
  seq.find(T item => { 
    boolean res = true;
    if (test(item)) {
      vec.add(item); 
      res = false;
    }
    return res;
  });
  return vec;      
}

<Any T> void eachUntil(Sequence<T> seq, T->boolean test, T->void func) {
  try {
    for(int i = 0; test(seq[i]); i++) {
      func(seq[i]);
    } 
  } catch (ArrayIndexOutOfBoundsException e) {
    //nothing
  }
}

<Any T> void eachFrom(Sequence<T> seq, T->boolean test, T->void func) {
  try {
    int i = 0;
    for(;!test(seq[i]);i++) {}     
    for(;; i++) {
      func(seq[i]);
    } 
  } catch (ArrayIndexOutOfBoundsException e) {
    //nothing
  }
}

<Any T> Sequence<T> dropWhile(Sequence<T> seq, T->boolean test) {
  Vector<T> vec = makeVector(10);
  int len = size(seq);
  boolean failed = false;
  for(int i = 0; i < len; i++) {    
    if (failed) {
      vec.add(seq[i]);
    } else if (test(seq[i])) {
      failed = true;
      vec.add(seq[i]);
    }
  }
  return vec;
}

<Any T> (Sequence<T>, Sequence<T>) span(Sequence<T> seq, T->boolean test) = (seq.takeWhile(test), seq.dropWhile(test));
<Any T> (Sequence<T>, Sequence<T>) brk(Sequence<T> seq, T->boolean test) = seq.span(compose(not, test));

Vector<String> lines(String s) {
  java.util.StringTokenizer strtok = new java.util.StringTokenizer(s, "\n");
  return makeLV(() => {
    if (!strtok.hasMoreTokens()) {
      indexError();
    }
    //return notNull(strtok.nextToken());
    return cast(strtok.nextToken());
  });
}

//TODO: accept other whitespace than " ", like the Haskell function does.
Vector<String> words(String s) {
  java.util.StringTokenizer strtok = new java.util.StringTokenizer(s, " ");
  return makeLV(() => {
    if (!strtok.hasMoreTokens()) {
      indexError();
    }
    //return notNull(strtok.nextToken());
    return cast(strtok.nextToken());
  });
}

String unlines(Sequence<String> seq) = seq.map(String s => s + "\n").foldLeft1(concat);

String unwords(Sequence<String> seq) = seq.map(String s => s + " ").foldLeft1(concat);

<Any A> Sequence<A> reverse(Sequence<A> seq) {
  int seqSize = size(seq);
  Vector<A> vec = makeVector(seqSize);
  for(int i = seqSize - 1; i >= 0; i--) {
    vec.add(seq[i]);
  }
  return vec;
}

boolean and(Sequence<boolean> seq) {
  for(int i = 0; i < seq.size(); i++) {
    if (!seq[i])
      return false;
  }
  return true;
}

//or is defined in prelude.nice

<Any T>boolean all(Sequence<T> seq, T->boolean test) {
  //or we could use: and(seq.map(test));
  for(int i = 0; i < seq.size(); i++) {
    if (!test(seq[i]))
      return false;
  }
  return true;
}

//any is equivalent to prelude.nice.has().

<Any T>boolean elem(Sequence<T> seq, T item) = seq.has(T each => each.equals(item));

<Any T>boolean notElem(Sequence<T> seq, T item) = seq.has(T each => !each.equals(item));


<Any T, Any U> ?U lookup(Sequence<(T,!U)> seq, T key) {
for(int i = 0; i < seq.size(); i++) {
  (T k, !U value) = seq[i];
  if (equals(k, key))
    return value; 
}
return null;
} 

//Needed for sum and product
// Number plus(Number one, Number two) = one + two;
// Number mult(Number one, Number two) = one * two;

// <Number T> T sum(Sequence<T> seq) = seq.foldLeft(plus, 0);

// <Number T> T product(Sequence<T> seq) = seq.foldLeft(mult, 1);

long min(Sequence<long> s) {
  long res=0;

  for(int i=0; i<s.size(); i++)
    if(s.get(i)<res)
      res=s.get(i);

  return res;
}

//maximum and minimum are max and min in Nice.

//String isn't a Sequence, so this could be tricky...
//<Collection C, Any T, Any U> Sequence<U> concatMap(C<T> coll, T->U xform) = concat(coll.map(xform));

<Any T, Any U> Sequence<(T,U)> zip(Sequence<T> tSeq, Sequence<U> uSeq) = zipWith((T t, U u) => (t, u), tSeq, uSeq);

<Any T, Any U, Any V> Sequence<(T,U,V)> zip3(Sequence<T> tSeq, Sequence<U> uSeq, Sequence<V> vSeq) = 
  zipWith3((T t, U u, V v) => (t, u, v), tSeq, uSeq, vSeq);

<Any T, Any U, Any V> Sequence<V> zipWith((T,U)->V func, Sequence<T> tSeq, Sequence<U> uSeq) {
  int minLen = min(size(tSeq), size(uSeq));
  Vector<V> vec = makeVector(minLen);
  for(int i = 0; i < minLen; i++) {
    vec.add(func(tSeq[i], uSeq[i]));
  }
  return vec;
}

<Any T, Any U, Any V, Any W> Sequence<W> zipWith3((T,U,V)->W func, Sequence<T> tSeq, Sequence<U> uSeq, Sequence<V> vSeq) {
  int minLen = min(size(tSeq), size(uSeq));
  Vector<W> vec = makeVector(minLen);
  for(int i = 0; i < minLen; i++) {
    vec.add(func(tSeq[i], uSeq[i], vSeq[i]));
  }
  return vec;
}

<Any T, Any U> (Sequence<T>, Sequence<U>) unzip(Sequence<(T,U)> seq) {
  Vector<T> tVec = makeVector(size(seq));
  Vector<U> uVec = makeVector(size(seq));
  seq.foreach((T,U) tup => {
    tVec.add(fst(tup));
    uVec.add(snd(tup));
  });
  return (tVec, uVec);
}

<Any T, Any U, Any V> (Sequence<T>, Sequence<U>, Sequence<V>) unzip3(Sequence<(T,U,V)> seq) {
  int len = size(seq);
  Vector<T> tVec = makeVector(len);
  Vector<U> uVec = makeVector(len);
  Vector<V> vVec = makeVector(len);
  seq.foreach((T,U,V) tup => {
    tVec.add(fst3(tup));
    uVec.add(snd3(tup));
    vVec.add(thrd(tup));    
  });
  return (tVec, uVec, vVec);
}

Topic HaskellPreludeExample . { Edit | Attach | Ref-By | Printable | Diffs | r1.1 | More }
Revision r1.1 - 30 Jan 2003 - 00:07 GMT - TWikiGuest
Parents: WebHome > CodeExamples
Copyright © 1999-2003 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback.