Apparently Amanda (the Windows equivalent of Miranda) itself has an equivalent called Tina. Moreover, if my memory is correct, there exists a language combining Java with functional programming features called Pizza. Note: I cannot prove either of these two assertions.

On a less serious note, there are some subtle difference between Miranda (Unix) and Amanda (Windows). It is not possible to simple copy code from one OS to another, although a majority of it should be fine.

|| TestStuff.ama date == (num, num, num) || doubleExp || given a list of numbers return a list of the whole number components of the square roots of the doubles of those numbers || round() would be replaced by entier() in Miranda doubleExp :: [num] -> [num] doubleExp [] = [] doubleExp (x:xs) = round( sqrt( (x * 2) ) ) : doubleExp xs || prodEven || given a list of numbers returns the product of all the even numbers in the list prodEven :: [num] -> num prodEven [] = 1 prodEven (x:xs) = x * prodEven(xs), if x mod 2 = 0 = prodEven(xs), otherwise || isDate || checks if a date is legal isDate :: date -> bool isDate (d, m, y) = okDayAndMonth(d, m) /\ okYear(d,m,y) okDayAndMonth :: (num, num) -> bool okDayAndMonth (d, m) = d <= [31,29,31,30,31,30,31,31,30,31,30,31] ! (m-1), if ( m > 0 /\ m <= 12 /\ d > 0) = False, otherwise || do it with the [if otherwise], so that the list is not indexed out of bounds by an invalid day number okYear :: date -> bool okYear (d,2,y) = d <= 28, if (y % 4 ~= 0) = False, otherwise okYear anyMonth = True || hdr || return last item only in the list hdr :: [*] -> * hdr [] = error "hdr unexpected empty list" hdr (x:xs) = xs ! (#xs - 1) || tlr || return all items in list excluding the last item tlr :: [*] -> [*] tlr (x:[]) = [] tlr (x:xs) = x : tlr xs || indexr || index item in list from end, not start indexr :: ([*],num) -> * indexr (x:xs, n) = xs ! (#xs - n-1), if n < #xs || -1 because miranda indexes from 0 = x, otherwise indexr2 :: ([*],num) -> * indexr2 (any, n) = any ! (#any -n) || consr, problem with ++, expects a list?? || append a list to an item || consr :: ([*],*) -> [*] consr (x, any) = any ++ [x] || anyUCS, stack recursion anyUCS :: [*] -> bool anyUCS [] = False anyUCS (x:xs) = True, if 'A' <= x /\ x <= 'Z' = True, if anyUCS(xs) = False, otherwise || anyUCA, stack accumulative recursion anyUCA :: [*] -> bool anyUCA any = xanyUC (any, False) where xanyUC (x:xs, status) = xanyUC (xs, isUpper x \/ status) xanyUC ([], status) = status isUpper c = 'A' <= c /\ c <= 'Z' || smallestN || takes the N smallest numbers from a number list, showing the result in ascending order smallestN :: (num,[num]) -> [num] smallestN (n,[]) = [] smallestN (n,x) = getList (x, []) where getList(x, nx)

> Author: Jack Wootton Last modified: 04/04/05 a typw synonym for a 24 clock > clock == (num, num, num) > string == [char] > stringHours = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve"] isIn returns True if an item exists within a list and False if it doesn't. Used throughout this file. > isIn :: ([*],*) -> bool > isIn ([], anything) = False > isIn (x:xs, x) = True > isIn (x:xs, notX) = isIn(xs, notX) validTime Check if a time is valid using a 24-hour clock > validTime :: clock -> bool > validTime (h,m,s) = okHr h & okMnSc m & okMnSc s > where > okHr h = posOne h & h < 24 > okMnSc i = posOne i & i < 60 > posOne i = i >= 0 & integer i timeDiff Output the number of minutes between any two valid times (ignoring seconds) > timeDiff :: (num, num, num, num, num, num) -> num > timeDiff (h, m, s, h1, m1, s1) = ( (h1 - h) * 60) + (m1 - m), if h1 >= h & validTime(h,m,s) & validTime(h1,m1,s1) > = (( (h1 + 24) - h) * 60) + (m1 - m), validTime(h,m,s) & validTime(h1,m1,s1) > = error "timeDiff expects a valid time", otherwise displayTime Show a valid time in words to the nearest quarterhour, using a 12-hour display > displayTime :: clock -> string > displayTime (h,m,s) = getMins((m*60)+s) ++ stringHours ! ((h-1) mod 12) ++ getAmPm h, if ((m*60)+s) <= 2250 > = getMins((m*60)+s) ++ stringHours ! (h mod 12) ++ getAmPm h, otherwise > where > getMins m = "Quarter to ", if 2250 < m < 3210 > = "Half past ", if 1410 < m <= 2250 > = "Quarter past ", if 450 < m <=1410 > = "", otherwise > > getAmPm i = " am", if i < 12 > = " pm", otherwise trebleCube Given a list of numbers returns a list of those numbers, cubed and then trebled > trebleCube :: [num] -> [num] > trebleCube [] = [] > trebleCube (x:xs) = (3 * (x * x * x)) : trebleCube(xs) prodOdd Given a list of numbers returns the product of all the odd numbers in the list > prodOdd :: [num] -> num > prodOdd [] = 1 > prodOdd (x:xs) = x * prodOdd(xs), if x mod 2 ~= 0 > = prodOdd(xs), otherwise allDifferentS Evaluates to True if all items in a list are different using stack recursion > allDifferentS :: [*] -> bool > allDifferentS [] = True > allDifferentS (x:xs) = ~ isIn(xs,x) & allDifferentS xs allDifferentA Evaluates to True if all items in a list are different using accumulative recursion > allDifferentA :: [*] -> bool > allDifferentA [] = True > allDifferentA (x:xs) = xDifferent(xs, True) > where > xDifferent(x:xs, status) = xDifferent( xs, ~isIn(xs,x) & status) > xDifferent([], status) = status Compare two versions allDifferentS: Each time the recursive call is made, a computation is postponed and the functiona call gets bigger. allDifferentS is the postponed calculation (it must be postponed and put on the stack while the next function call is made). In stack recursion this means more of the stacks memory is used each time a computation is postponed. This is inefficient and could cause problems for more processor intensive calculations. Because logical conjunction is used the possiblity of using lazy evaluation is removed because of this, the best time growth rate is only O(N). allDifferentA: Retruns a result after xDifferent has finished its calculations. The extra function stops the calculation calls from being stored on the stack as a status value is used to keep a total as the function moves through the list. Calculations are kept in the status value rather than on the stack, however the entire list is still traversed so the best time growth is O(N) separate Given a list of numbers will return a pair of lists, where the first list contains the even numbers and the second list contains the odd numbers > separate :: [num] -> ([num],[num]) > separate xs = xseparate ([],[],xs) > where > xseparate (x,y,[]) = (x,y) > xseparate (x,y,a:as) = xseparate(x,y,as), if ~ (integer a) > = xseparate(x ++ [a], y, as), if a mod 2 ~= 0 > = xseparate(x, y ++ [a], as), otherwise smerge Given two strings, both having standard lexigraphical ordering, will merge them into one string. If either string is not ordered then an error should be reported > smerge :: (string, string) -> string > smerge (x:xs, y:ys) = xsmerge(x:xs, y:ys), if ordered(xs,x) & ordered(ys,y) > = error "smerge expects lexigraphically ordered strings", otherwise > where > ordered ([],a) = True > ordered (x:xs, a) = a <= x & ordered(xs,x) > > xsmerge([],any) = any > xsmerge(any,[]) = any > xsmerge(x:xs, y:ys) = x : xsmerge(xs,y:ys), if x < y > = y : xsmerge(x:xs,ys), otherwise intersect Given a list of lists produces a list containing one instance of items that appear in all of the lists > intersect :: [[*]] -> [*] > intersect [] = [] > intersect x = xintersect x > where > xintersect [] = error "error" > xintersect([]:other) = [] > xintersect [other] = other > xintersect(x:xs) = [hd x] ++ xintersect( (tl x) :xs), isInAll (xs, hd x) > = intersect( (tl x):xs), otherwise > where > isInAll([], item) = True > isInAll(x:xs,item) = isIn(x, item) & isInAll(xs, item) case analysis = used to check correct and incorrect input for both intersect and xintersect and that all base cases of these functions were covered. intersect [] = [] intersect x = xintersect x xintersect [] = error "error" xintersect [other] = other xintersect([]:other) = [] structural induction was used to help design function recursion and started by making use of the above case analysis. isInAll([], item) evaluates to true becasue xintersect never passes an empty list to it structural induction for isIn isIn ([], anything) = False isIn (x:xs, x) = True isIn (x:xs, notX) = isIn(xs, notX) C/C++ string handling Returns 1 if string x > string y, -1 if string x < string y, and 0 if they're the same (cse insensitive) > strcmp :: (string, string) -> num > strcmp (x,y) = 1, if x > y > = -1, if x < y > = 0, otherwise Returns 1 if string x > string y, -1 if string x < string y, and 0 if they're the same (cse sensitive) > strcasecmp :: (string, string) -> num > strcasecmp (x,y) = strcmp(lower x, lower y) > where > lower [] = [] > lower (x:xs) = decode (code x+32) : lower xs, if 65 <= code x <= 90 > = x : lower xs, otherwise Position of first instance of a specified character in a string > strchr :: (string, char) -> num > strchr (xs, c) = getPos(xs, c, 0) > where > getPos ([], c, i) = error "cannot find specified char" > getPos(y:ys, c, i) = i+1, if c = y > = getPos(ys, c, i+1), otherwise Position of last instance of a specified character in a string > strrchr :: (string, char) -> num > strrchr (xs, c) = getRPos(xs, c, #xs) > where > getRPos ([], d, i) = error "cannot find specified char" > getRPos(ys, d, i) = i, if (ys ! (i-1)) = d > = getRPos(ys, d, i-1), otherwise Append a specified number of chars to a string, from another > strncat :: (string, string, num) -> string > strncat (s, t, 0) = s > strncat (xs, y:ys, n) = error "number to large", if n > #(y:ys) > = strncat(xs ++ [y], ys, n-1), otherwise Create a copy of a string > strdup :: string -> string > strdup any = any Start position of a substring in another string > strstr :: (string, string) -> num > strstr (any, []) = error "strstr expects substring of one or more characters" > strstr any = xstrstr any > where > xstrstr ([],[]) = 1 > xstrstr(x, []) = 1 > xstrstr([], y) = 0 > xstrstr(x:xs, x:ys) = 1, if xstrstr(xs, ys) > 0 > = xstrstr(xs, x:ys) + 1, if xstrstr(xs, x:ys) > 0 > = 0, otherwise > xstrstr(x:xs, any) = xstrstr(xs, any) + 1, if xstrstr(xs, any) > 0 > = 0, otherwise Miranda does not require any pointers where as any string methods in c would require pointers and c++ would require either pointers or a class wrapper for string. All memory functions are hidden from the programmer and therefore programming time is reduced. Although a string of characters and a Miranda list of characters is structurely similar the access methods and built in list methods in Miranda make string operation many times easier. There is also a danger in c/c++ that the orignal values of the strings may be lost or changed. In Miranda the original values are completely safe. strcmp = would need to derference pointers for each char and also make sure that pointers do not reference an index position out of a char arrays bounds in c/c++. Even simple methods such as strdup would require creating a copy of an array of pointers...an ugly task as the best of times.