我试图在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包?
答案 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