Advanced examples
This page presents some advanced programming examples in CDuce.If you never saw CDuce programs before, this is the wrong pageto start with. Rather follow our (Tutorial) , or test the simple examples in ouron line demo.
(Our canonical example)
The example below is the one we use to demonstrate how overloaded functions can avoid duplicating code. Without overloaded functions, we would need to define two mutually recursive functions in order to type-check the transformation. Here, two constraints in the (highlighted) function interface can express precisely the behavior of the function. A detailed explanation of the code can be foundhere.
type Person=FPerson | MPerson type FPerson=[ Name Children ] type MPerson= [ Name Children ] type Children= [ Person* ] type Name= [ PCDATA ] type Man= [ Sons Daughters ] type Woman= [ Sons Daughters ] type Sons= [ Man* ] type Daughters= [ Woman* ] let fun split ( (MPerson ->Man; FPerson ->Woman) ) [ n [(mc::MPerson | fc::FPerson)*]] -> the above pattern collects all the MPerson in mc, and all the FPerson in fc let tag=match g with "F" ->`woman | "M" ->`man in let s=map mc with x ->split x in let d=map fc with x ->split x in [ s d ]; ;
Datatypes first-class functions
The program below shows how to simulate ML data types in CDuce. It implements a (naive backtracking) regular expression recognizer. The examples also demonstrate the use of first-class functions (used as continuations).
Exercise for the reader: show that the algorithm may not terminate for some special regular expressions.
type regexp=Char | (regexp, regexp) | (regexp, regexp) | Regexp type f=String ->Bool let loop (re: regexp, k: f): f=fun (s: String): Bool=match re with | p ->(match s with ( c, s) ->(c=p) && (ks) | _ ->`false) | (r1, r2) ->loop (r1, (loop (r2, k))) s | (R1, R2) ->loop (r1, k) s || loop (r2, k) s | (r ->loop) r, (loop (re, k))) s || k s let accept (re: regexp): f= loop (re, fun (String ->Bool) [] ->`true | _ ->` false) let re= ( 'A', 'b') let strs=[ "aaabbb" "abba" "aaab" "a" "" ] let []=print ((string_of (map strs with x ->(x, accept re x))) @ ['n'])
First-class functions and XML together
The program below illustrates the use of first-class functions stored in (pseudo) XML documents.
type Bib=[ Book* ] type Book=[ Title Subtitle? Author ] type Title= [ PCDATA ] type Subtitle= [ PCDATA ] type Author= [ PCDATA ] let title (Book ->String) [ x _* ] ->x let author (Book ->[Author ]) x ->x // Author We annotate each book with a printing function for it type FBook=Book ->String type ABook= [ Title Subtitle? Author ] type ABib=[ ABook* ] Note that: ABook c: Book) (f: FBook): ABook= c let prepare (b: Bib): ABib=map b with x ->set x title We display the annotated bibliography type Ul= [ Li ] type Li=[ PCDATA ] let display (ABib ->Ul; ABook ->Li) |
_ & x -> - (fx) | [] ->raise "Empty bibliography" | p ->
(map p with z ->display z) We change the dispay function for some books let change (p: Book ->Bool) (f: FBook) (b: ABib): ABib= map b with x ->if (p x) then set x f else x type HasSub=<_>[ _* Subtitle _* ] let change_if_sub= change (fun (Book ->Bool) HasSub ->`true | _ ->` false)
(CDuce quine)
A quine (a.k.a. self-rep) is a program that produces its own source code. Here is an example of a quine written in CDuce.
let data=" print ['let data=##' !data '## in']; let fun f (Latin1 ->Latin1) | [ '#' '#'; s ] ->[ '##'; f s ] | [ c; s ] ->[ c; f s ] | [] ->[] in print (f data) "in print ['let data="' !data '" in']; let fun f (Latin1 ->Latin1) | [ '#' '#'; s ] ->[ '"'; f s ] | [ c; s ] ->[ c; f s ] | [] ->[] in print (f data)
The script that generates this site
The script below is one of the longest CDuce application ever written 😉 It is used to produce all the pages of this web site (except Theweb prototypewhich is a CGI script written in OCaml). CDuce type system ensures that produced pages are valid w.r.t XHTML 1.0 Strict.
This program features both XML and text-content manipulation. It also demonstrates the use of non-XML internal data structures. Here, a tree represents internally the site structure, and a list represents the path from the root to the current page (in order to display the “You’re here” line).
This CDuce script produces CDuce web site. The types include "siteTypes.cd" ;; Command line let (input, outdir)= match argv [] with | [ s ("-o" o | /(o :="www")) ] ->(s, o) | _ ->raise "Please use --arg to specify an input file on the command line" Generic purpose functions Recursive inclusion of XML files and verbatim text files let load_include (Latin1 ->[Any*]) name ->let _=print [ 'Loading ' !name '... n' ] in xtransform [ (load_xml name) ] with |[] ->load_include s | [] ->load_file s | [] -> match load_xml ("string: "@ (load_file s) @" ") withx ->x | _ ->raise "Uhh?" Loading let [ [ site ( header | / (header:=[])) (
GIPHY App Key not set. Please check settings