viewpp: A Haskell Preprocessor for updatable viewsThis is an implementation of the paper "Translucent Abstraction: Safe Views through Invertible Programming" written by Meng Wang et al.
With this system, in Haskell, you can access the same data structure by two different interfaces as follows.
type Queue a = ([a],[a])
viewdata Queue a @ List a = Nil | Cons a where
view :: Queue a :~>: List a
view = (idB <**> reverseB) >>>> appendB >>>> $(toC L)
-- enQ defined on source
enQ :: a -> Queue a -> Queue a
enQ a (x,y) = (x,a:y)
-- deQ defined on view
deQ :: Queue a -> Queue a
deQ (Cons a x) = x
-- sourceQ/insQ defined on view
sortQ :: Ord a => Queue a -> Queue a
sortQ Nil = Nil
sortQ (Cons ax) = ins a (sortQ x)
ins :: Ord a => a -> Queue a -> Queue a
ins a Nil = a
ins a (Cons b x)
| a <= b = Cons a (Cons b x)
| a > b = Cons b (ins a x)
Since the views are defined by bidirectional language rinv, you can accees the original data by both decomposing and composing the views.
Using this system is quite easy; just use it as a preprocessor for GHC. If you want to compile "FILENAME.hs" including viewdata, just type as follows.
> ghc -F -pgmF viewpp FILENAME.hs
Of cource, you can use the system through ghci interpreter.
> ghci -F -pgmF viewpp FILENAME.hs
tar zxvf viewpp.tar.gzmakeviewpp (or, viewpp.exe in Windows) is the name of the preprocessor.examples contains some examples.lib contains Haskell source files for view data.Since the module name of the libraries for updatable views are still tentative, we do not install them automatically. Please put the files under lib directory to your favorite place and include them by -iDIRECTORY in compilation.
rinv: Right-Inverse LanguageIn our framework, views are defined by bidirectional transformations described by rinv language. Thanks to the properties guaranteed by the rinv language, we can avoid the situations that view updating result is counter-intuitive for users.
As the above example, rinv is pointfree combinator-based language. You can use the following premitives in the language.
f >>>> gSequential composition of two transformations.
f <**> gApplication of "f" and "g" to each element of pairs.
f <&&> gIt tuples the result of application of "f" and "g" to input.
f <||> gIt applies "f" if the input is Left x, and applies "g" if the input is Right x.
f <++> gSimilar to above but it keeps tags (Left/Right).
$(toC C')This applies the constructor C to the input.
idBIt just returns input as is.
$(fold ''T)The function is "fold" on datatype T. This combinator is not implemented yet. Currently, users are required to define "fold"s on view datatypes using $(fromT ''T) combinator that introces pairs and sums from datatype declaration. For example, "fold" on List a is defined as
foldListB fB = $(fromT ''List) >>>> right (second (foldListB fB)) >>>> fB
Users also can use predefined combinators as reverseB and appendB.
One would think why do we use Arrows. However, because of bidirectionality, this language does not follow Arrow laws. For example, arr id >>>> f = f does not hold because arr id does not know anything about inverse direction.
Our system is defined as preprocessor for GHC. Since we hope that some people interested in how the above "viewdata" codes are translated to Haskell code, we put here some of translation examples.
| Short Description | Code with viewdata | Preprocessed Result |
|---|---|---|
| Cons/Snoc | cs.hs | cs.hspp |
| Queue/List | ql.hs | ql.hspp |
| SizedTree | sizedtree.hs | sizedtree.hspp |
| Binary Number | MSBLSB.hs | MSBLSB.hspp |
For the implementation reason, the current implementation has the following limitation.
viewdata declation only accepts Haskell 98 style of data type declaration.viewdata must have kind *.List (List a) does not work.And, the following is known bug.
If you have found other bugs, we would appricate it if you would send me a bug report to .
Thank you.
Kazutaka Matsuda: .The first version of this page was published in 2009-05-08.