Haskell 广义多参数函数提升的类型类技巧
我想将Haskell函数提升到高阶lambda演算编码中。这几乎是从Oleg的类型化无标记最终编码中一字不差地提取出来的Haskell 广义多参数函数提升的类型类技巧,haskell,dsl,typeclass,lifting,Haskell,Dsl,Typeclass,Lifting,我想将Haskell函数提升到高阶lambda演算编码中。这几乎是从Oleg的类型化无标记最终编码中一字不差地提取出来的 class Lam r where emb :: a -> r a (^) :: r (r a -> r a) -> (r a -> r a) lam :: (r a -> r a) -> r (r a -> r a) instance Lam Identity where emb = Identity f
class Lam r where
emb :: a -> r a
(^) :: r (r a -> r a) -> (r a -> r a)
lam :: (r a -> r a) -> r (r a -> r a)
instance Lam Identity where
emb = Identity
f ^ x = f >>= ($ x)
lam f = return (f . return =<<) -- call-by-value
eval = runIdentity
不过,这是很多陈词滥调。我想创建一个通用的提升函数,它适用于任何算术函数。我觉得可以使用类似于Printf
的PrintfType
或固定向量的Cont
类型。我可以使用类型函数指定所需的内容
type family Low h o
type instance Low () o = o
type instance Low (a, h) o = a -> Low h o
type family Lift r h o
type instance Lift r () o = o
type instance Lift r (a, h) o = r a -> r (Lift r h o)
class Emb r h o where
embed :: Low h o -> r (Lift r h o)
instance ( Lam r ) => Emb r () o where
embed = emb
instance ( Lam r, Applicative r, Emb r h o ) => Emb r (a, h) o where
embed = ?
但是通过这种方法,我陷入了困境,通常是由于注入性问题。我能够用一个新类型包装器和作用域类型变量的真正可怕的组合来解析注入性,但它实际上从未进行过类型检查
这可以用Haskell表达吗?您可能想看看
以无标签的最终风格。诀窍是在对象语言中泛化箭头类型。事实上我们经常使用Haskell's
对象语言中函数类型(要嵌入)的类型构造函数->
是一种巧合和方便。通常,对象函数不会简单地映射到Haskell函数。参考文章中的代码包含ESymantics
-- How to interpret arrows and other types
type family Arr (repr :: * -> *) (a :: *) (b :: *) :: *
class ESymantics repr where
int :: Int -> repr Int
add :: repr Int -> repr Int -> repr Int
lam :: (repr a -> repr b) -> repr (Arr repr a b)
app :: repr (Arr repr a b) -> repr a -> repr b
现在,我们有足够的自由根据特定的报告来解释Arr。引用的文章为CPS实例解释Arr
编辑:事实证明,我们可以达到同样的效果——重新定义对象语言箭头的含义——而不引入Arr类型(及其内射性问题)和ESemantics。上面链接到普通和一次性CPS转换,显示了使用标准语义并重新解释函数类型构造函数含义的新代码。不再存在任何注入性问题。我不知道答案,但下一个链接可能会有所帮助:我昨晚查看了这个链接,发现它提供了很多信息,但我需要找出如何最好地处理类型族的非注入性问题。我认为我通常对Haskell arrows将坚持使用对象语言表示的期望过高。感谢您的回复!
-- How to interpret arrows and other types
type family Arr (repr :: * -> *) (a :: *) (b :: *) :: *
class ESymantics repr where
int :: Int -> repr Int
add :: repr Int -> repr Int -> repr Int
lam :: (repr a -> repr b) -> repr (Arr repr a b)
app :: repr (Arr repr a b) -> repr a -> repr b