viewpp: A Haskell Preprocessor for updatable views

What is this?

This 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 

How to build

  1. Download tar file: viewpp.tar.gz
  2. Unpack the tar file: tar zxvf viewpp.tar.gz
  3. make

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 Language

In 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 >>>> g

Sequential composition of two transformations.

f <**> g

Application of "f" and "g" to each element of pairs.

f <&&> g

It tuples the result of application of "f" and "g" to input.

f <||> g

It applies "f" if the input is Left x, and applies "g" if the input is Right x.

f <++> g

Similar to above but it keeps tags (Left/Right).

$(toC C')

This applies the constructor C to the input.

idB

It 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.

Code Translation Example

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 DescriptionCode with viewdataPreprocessed Result
Cons/Snoc cs.hs cs.hspp
Queue/List ql.hs ql.hspp
SizedTree sizedtree.hs sizedtree.hspp
Binary Number MSBLSB.hs MSBLSB.hspp

Limitations & Known Issues

For the implementation reason, the current implementation has the following limitation.

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.