“隐式配置”代码的代码

时间:2013-02-09 19:30:55

标签: haskell ghci

我试图在ghci中运行此代码:

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

这是与论文相关的代码"功能珍珠:隐式配置"

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

我确定我错过了一些LANGUAGE个pragma ...我收到以下错误:

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

此外,是否有任何与本文相关的hackage包?

3 个答案:

答案 0 :(得分:4)

您无法将类型签名应用于函数定义模式。这是编写它的语法正确的方法:

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

然而,这是行不通的。你真正想要的是在函数的类型签名中引用类型变量 s 。这可以通过使用ScopedTypeVariables扩展来完成,这需要显式量化:

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

作为改进代码的建议,我建议使用标记的库:

import Data.Proxy

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

这可以让你在没有丑陋的占位符底部的情况下相处。另一种写作方式是:

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

这也为您带来了很好的概念上的好处:您现在有两种类型,模块值为Mod,模块为Tagged。你也可以自己定义类型,给它一个更好的名字:

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

除此之外,如果你想实际使用它,我建议ocharles说:使用reflection库。

答案 1 :(得分:3)

我无法解决代码问题,但Edward Kmett的`reflection'库基于该论文。

答案 2 :(得分:2)

这完成了使用reflection库的论文中的示例。我将此示例基于库源中的Monoid示例。

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