3

我正在尝试在以下位置运行此代码ghci

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

这是与论文“Functional Pearl: Implicit Configurations”相关的代码

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

我确定我缺少一些LANGUAGE编译指示...我收到以下错误:

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

另外,是否有与本文相关的黑客包?

4

3 回答 3

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 所说的:使用反射库。

于 2013-02-09T20:24:14.277 回答
3

我无法解决代码问题,但 Edward Kmett 的“反射”库是基于那篇论文的。

于 2013-02-09T19:45:31.920 回答
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
于 2013-02-09T20:38:13.397 回答