Code for paper "Implicit configurations"

I am trying to run this code in ghci

:

http://www.cs.rutgers.edu/~ccshan/prepose/Prepose.hs

This is the code associated with Functional Gem: Implicit Configurations

http://www.cs.rutgers.edu/~ccshan/prepose/prepose.pdf

I'm sure I am missing some LANGUAGE

pragmas ... I am getting the following error:

Prepose.hs:39:1: Parse error in pattern: normalize

      

Also, are there any hacker packages associated with this article?

+3


source to share


3 answers


You cannot apply a type signature to a function definition template. This is the syntactically correct way of writing:

normalize :: (Modular s a, Integral a) => a -> M s a
normalize a = M (mod a (modulus (__ :: s))) :: M s a

      

However, this will not work. What you really want is to reference a variable of type s in the function's type signature. This can be done using the ScopedTypeVariables extension, which requires explicit quantification:

normalize :: forall a s. (Modular s a, Integral a) => a -> M s a
normalize x = M (Mod x (modulus (__ :: s)))

      

As a suggestion for improving the code, I recommend using the tagged library:

import Data.Proxy

modulus :: (Modular s a) => Proxy s -> a

      



This allows you to do without ugly blanks. Another way to write it down:

modulus :: (Modular s a) => Tagged s a

      

It also gives you a nice conceptual benefit: you now have two types: Mod

for modular values ​​and Tagged

for their modules. You can also define the type by giving it a nicer name:

newtype Mod     s a = Mod     { residue :: a } 
newtype Modulus s a = Modulus { modulus :: a }

      

All this aside, if you want to use this I recommend what ocharles said: Use the reflection library .

+4


source


I can't help with the code problem, but Edward Kemat's `reflection ' library is based on this article.



+3


source


This completes the example from the article using the library reflection

. I am basing this example on the example Monoid

in the library source.

data M a s = M a -- Note the phantom comes *after* the concrete

-- In `normalize` we're tying the knot to get the phantom types to align
-- note that reflect :: Reifies s a => forall proxy. proxy s -> a

normalize :: (Reifies s a, Integral a) => a -> M a s
normalize a = b where b = M (mod a (reflect b)) 

instance (Reifies s a, Integral a) => Num (M a s) where
  M a + M b = normalize (a + b)
  ...

withModulus :: Integral a => a -> (forall s. Reifies s a => M a s) -> a
withModulus m ma = reify m (runM . asProxyOf ma)
  where asProxyOf :: f s -> Proxy s -> f s
        asProxyOf a _ = a

      

+2


source







All Articles