Curry - gregorymorrison/euler1 GitHub Wiki
(from Wikipedia) Curry is an experimental functional logic programming language, based on the Haskell language. It merges elements of functional and logic programming, including constraint programming integration.
Here is a simple example of Euler1 using a list comprehension and a summation function:
-- Euler1 in Curry
euler1 :: Int -> Int
euler1 n = foldr (+) 0 [x | x <- [0..n], x `mod` 3 == 0 || x `mod` 5 == 0]
main = putstrln (euler1 999)
Curry has full support for functional operations. Here’s an example using the canonical functions map, filter, and fold. Map’s only purpose here obviously is for illustration, since it returns itself. It also demonstrates use of lambda - an anonymous inline function using the \ operator, and function composition, where we chain together our three functions with the $ operator:
-- Euler1 in Curry
myMap xs = map id xs
myFilter xs = filter (\ x -> x `mod` 3 == 0 || x `mod` 5 == 0) xs
myFold xs = foldr (+) 0 xs
euler1 :: Int -> Int
euler1 n = myFold $ myFilter $ myMap [1 .. n]
main = print (euler1 (999))
Notice that we are not maintaining any state to solve our problem. No loops, no variables, no mutable state – only function application. We simply call map, filter, and fold, and get the solution. This is an important part of the solution of the concurrency problem – how do you keep threads from stepping on each other’s states? By eliminating mutable state!
Here’s a functional version that uses tail recursion with an accumulator. One of the main points here is that the function euler() is deterministic – it will always return the same output for a given input. This is accomplished in part by the absence of any variable manipulation – there are instead only functions which return values. The other main point is that this recursion uses tail call optimization – it’s written in such a way that an intelligent compiler can optimize its stack usage to be O(n) instead of O(n!). In English, this means that your program will probably not crash even for hugely recursive calls.
-- Euler1 in Curry
mod_3_5 :: Int -> Int
mod_3_5 n
| n `mod` 3 == 0 = n
| n `mod` 5 == 0 = n
| otherwise = 0
euler1 :: Int -> Int
euler1 n = euler n 0
where euler n acc
| n == 0 = acc
| otherwise = euler (n-1) (acc + mod_3_5 n)
main = print (euler1 999)
Here’s one more – an elegant algorithm based on an observation by little Carl Friedrich Gauss. It operates in O(1) constant time. Don’t sweat it if this seems inscrutable; click the blog link above for an explanation:
-- Euler1 in Curry
import Float
mysum :: Int -> Int -> Int
mysum n size = (truncateFloat(floatFromInt(size `div` n)^2) + (size `div` n)) * n `div` 2
euler1 :: Int -> Int
euler1 n = mysum 3 n + mysum 5 n - mysum 15 n
main = print (euler1 999)
Curry also has an online interactive browser implementation that lets you kick the tires without any installation: http://www-ps.informatik.uni-kiel.de/~pakcs/webpakcs/main.cgi.
$ cyc -o euler1 euler1.curry
$ ./euler1
233168
$