Skip to content

Commit 8418a29

Browse files
committed
Tests and docs for the Curry type class
1 parent e336086 commit 8418a29

File tree

4 files changed

+182
-0
lines changed

4 files changed

+182
-0
lines changed

doc/libraries_ref_guide/LibDoc/Prelude.tex

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6311,12 +6311,59 @@ \subsubsection{Operations on Functions}
63116311
\end{tabular}
63126312
\end{center}
63136313

6314+
\index{Curry@\te{Curry} (type class)}
6315+
\index[typeclass]{Curry}
6316+
\index{curryN@\te{curryN} (function)}
6317+
\index[function]{Prelude!curryN}
6318+
\index{uncurryN@\te{uncurryN} (function)}
6319+
\index[function]{Prelude!uncurryN}
6320+
6321+
The \te{Curry} typeclass generalizes the \te{curry} and \te{uncurry} functions
6322+
to work with tuples of any size (not just Tuple2).
6323+
6324+
\begin{libverbatim}
6325+
typeclass Curry#(type f, type g)
6326+
dependencies (f determines g);
6327+
function g curryN(f x);
6328+
function f uncurryN(g x);
6329+
endtypeclass
6330+
\end{libverbatim}
6331+
6332+
\begin{center}
6333+
\begin{tabular}{|p{1 in}|p{4 in}|}
6334+
\hline
6335+
\te{curryN}&Converts an uncurried function (taking an N-tuple argument) into a curried
6336+
function (taking N arguments one at a time). For example, \te{curryN} can convert a
6337+
function taking \te{Tuple3\#(a,b,c)} into a function \te{a -> b -> c -> result}.\\
6338+
\hline
6339+
\te{uncurryN}&The inverse of \te{curryN}. Converts a curried function (taking N arguments
6340+
one at a time) into an uncurried function (taking an N-tuple argument).\\
6341+
\hline
6342+
\end{tabular}
6343+
\end{center}
6344+
63146345

63156346
{\bf Examples}
63166347

63176348
\begin{libverbatim}
63186349
//using constFn to set the initial values of the registers in a list
63196350
List#(Reg#(Resource)) items <- mapM( constFn(mkReg(initRes)),upto(1,numAdd) );
6351+
6352+
// Using curryN with a 3-tuple
6353+
function Int#(32) add3Tuple(Tuple3#(Int#(32), Int#(32), Int#(32)) t);
6354+
return tpl_1(t) + tpl_2(t) + tpl_3(t);
6355+
endfunction
6356+
6357+
let add3Curried = curryN(add3Tuple);
6358+
Int#(32) result = add3Curried(1)(2)(3); // result = 6
6359+
6360+
// Using uncurryN
6361+
function Int#(32) add3(Int#(32) a, Int#(32) b, Int#(32) c);
6362+
return a + b + c;
6363+
endfunction
6364+
6365+
let add3Uncurried = uncurryN(add3);
6366+
Int#(32) result2 = add3Uncurried(tuple3(1, 2, 3)); // result2 = 6
63206367

63216368
return(pack(map(compose(head0,toList),state)));
63226369

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
-----------------------------------------------------------------------
2+
-- Test for the Curry type class and curryN/uncurryN functions
3+
-----------------------------------------------------------------------
4+
5+
package CurryTypeClass where
6+
7+
import Vector
8+
9+
-----------------------------------------------------------------------
10+
-- Test with Tuple2
11+
-----------------------------------------------------------------------
12+
13+
add2Tuple :: (Int 32, Int 32) -> Int 32
14+
add2Tuple t = tpl_1 t + tpl_2 t
15+
16+
add2 :: Int 32 -> Int 32 -> Int 32
17+
add2 a b = a + b
18+
19+
testCurry2 :: Bool
20+
testCurry2 =
21+
let curried :: Int 32 -> Int 32 -> Int 32
22+
curried = curryN add2Tuple
23+
result1 :: Int 32
24+
result1 = curried 5 10
25+
uncurried :: (Int 32, Int 32) -> Int 32
26+
uncurried = uncurryN add2
27+
result2 :: Int 32
28+
result2 = uncurried (5, 10)
29+
in result1 == 15 && result2 == 15
30+
31+
32+
-----------------------------------------------------------------------
33+
-- Test with Tuple3
34+
-----------------------------------------------------------------------
35+
36+
add3Tuple :: (Int 32, Int 32, Int 32) -> Int 32
37+
add3Tuple t = tpl_1 t + tpl_2 t + tpl_3 t
38+
39+
add3 :: Int 32 -> Int 32 -> Int 32 -> Int 32
40+
add3 a b c = a + b + c
41+
42+
testCurry3 :: Bool
43+
testCurry3 =
44+
let curried :: Int 32 -> Int 32 -> Int 32 -> Int 32
45+
curried = curryN add3Tuple
46+
result1 :: Int 32
47+
result1 = curried 1 2 3
48+
uncurried :: (Int 32, Int 32, Int 32) -> Int 32
49+
uncurried = uncurryN add3
50+
result2 :: Int 32
51+
result2 = uncurried (1, 2, 3)
52+
in result1 == 6 && result2 == 6
53+
54+
55+
-----------------------------------------------------------------------
56+
-- Test with Tuple4
57+
-----------------------------------------------------------------------
58+
59+
add4Tuple :: (Int 32, Int 32, Int 32, Int 32) -> Int 32
60+
add4Tuple t = tpl_1 t + tpl_2 t + tpl_3 t + tpl_4 t
61+
62+
add4 :: Int 32 -> Int 32 -> Int 32 -> Int 32 -> Int 32
63+
add4 a b c d = a + b + c + d
64+
65+
testCurry4 :: Bool
66+
testCurry4 =
67+
let curried :: Int 32 -> Int 32 -> Int 32 -> Int 32 -> Int 32
68+
curried = curryN add4Tuple
69+
result1 :: Int 32
70+
result1 = curried 1 2 3 4
71+
uncurried :: (Int 32, Int 32, Int 32, Int 32) -> Int 32
72+
uncurried = uncurryN add4
73+
result2 :: Int 32
74+
result2 = uncurried (1, 2, 3, 4)
75+
in result1 == 10 && result2 == 10
76+
77+
78+
-----------------------------------------------------------------------
79+
-- Test roundtrip: curryN . uncurryN = id and uncurryN . curryN = id
80+
-----------------------------------------------------------------------
81+
82+
testRoundtrip :: Bool
83+
testRoundtrip =
84+
-- Test that uncurrying then currying gets back the original behavior
85+
let temp :: (Int 32, Int 32, Int 32) -> Int 32
86+
temp = uncurryN add3
87+
f1 :: Int 32 -> Int 32 -> Int 32 -> Int 32
88+
f1 = curryN temp
89+
result1 :: Int 32
90+
result1 = f1 10 20 30
91+
-- Test that currying then uncurrying gets back the original behavior
92+
f2 :: (Int 32, Int 32, Int 32) -> Int 32
93+
f2 = uncurryN (curryN add3Tuple)
94+
result2 :: Int 32
95+
result2 = f2 (10, 20, 30)
96+
in result1 == 60 && result2 == 60
97+
98+
99+
-----------------------------------------------------------------------
100+
-- Test with unit tuple (special case)
101+
-----------------------------------------------------------------------
102+
103+
fromUnitTuple :: () -> Int 32
104+
fromUnitTuple _ = 42
105+
106+
testUnitTuple :: Bool
107+
testUnitTuple =
108+
let curried :: Int 32
109+
curried = curryN fromUnitTuple
110+
in curried == 42
111+
112+
113+
-----------------------------------------------------------------------
114+
-- Module for testing
115+
-----------------------------------------------------------------------
116+
117+
{-# verilog sysCurryTypeClass #-}
118+
sysCurryTypeClass :: Module Empty
119+
sysCurryTypeClass =
120+
module
121+
rules
122+
"test": when True ==>
123+
action
124+
$display "Test Curry2: %b" testCurry2
125+
$display "Test Curry3: %b" testCurry3
126+
$display "Test Curry4: %b" testCurry4
127+
$display "Test Roundtrip: %b" testRoundtrip
128+
$display "Test Unit Tuple: %b" testUnitTuple
129+
$finish 0

testsuite/bsc.lib/Prelude/Prelude.exp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ compile_verilog_fail_no_internal_error Eq3
88
test_c_veri_bs_modules TuplePack {}
99
test_c_veri_bs_modules TupleSize {}
1010
test_c_veri_bs_modules AppendTuple {}
11+
test_c_veri_bs_modules CurryTypeClass {}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Test Curry2: 1
2+
Test Curry3: 1
3+
Test Curry4: 1
4+
Test Roundtrip: 1
5+
Test Unit Tuple: 1

0 commit comments

Comments
 (0)