让纯粹的λ函数成为除抽象和应用之外的任何术语。在JavaScript上,可以通过将所有抽象应用于收集其参数列表的可变参数函数来推断纯函数的源代码。也就是说,这是可能的:
lambdaSource(function(x){return x(x)}) == "λx.(x x)"
请参阅此要点的lambdaSource代码。这个函数对我的兴趣特别有用,因为它允许我使用现有的JS引擎来标准化无类型的lambda演算表达式,比我自己编写的任何天真评估器快得多。此外,我知道λ-calculus函数可以在unsafeCoerce
的帮助下在Haskell中表达:
(let (#) = unsafeCoerce in (\ f x -> (f # (f # (f # x)))))
由于缺少可变参数函数,我不知道如何在Haskell中实现lambdaSource
。是否有可能在Haskell上推断纯λ函数的归一化源,例如:
lambdaSource (\ f x -> f # (f # (f # x))) == "λ f x . f (f (f x))"
答案 0 :(得分:5)
是的,您can,但是您需要提供功能类型的主干,因此它对ULC不起作用。另请参阅整个lecture notes。
但正如 Daniel Wagner 所说,你可以使用HOAS。
还有另一个机会:这里something看起来像HOAS,但实际上是FOAS,你所需要的只是通过评估进行规范化(in terms of quote,in terms of reify & reflect)。 pigworker 还写了一个Haskell版本的Jigger,但我无法找到它。
我们也可以在类型理论中安全地做这种类型:一种方法是使用liftable terms(需要一个假设),或者我们可以reify lambda术语进入他们的PHOAS表示然后转换{ {3}}(这非常复杂)。
修改强>
以下是一些与HOAS相关的代码:
{-# LANGUAGE GADTs, FlexibleInstances #-}
infixl 5 #
data Term a = Pure a | Lam (Term a -> Term a) | App (Term a) (Term a)
(#) :: Term a -> Term a -> Term a
Lam f # x = f x
f # x = App f x
instance Show (Term String) where
show = go names where
names = map (:[]) ['a'..'z'] ++ map (++ ['\'']) names
go :: [String] -> Term String -> String
go ns (Pure n) = n
go (n:ns) (Lam f) = concat ["\\", n, " -> ", go ns (f (Pure n))]
go ns (App f x) = concat [go ns f, "(", go ns x, ")"]
k :: Term a
k = Lam $ \x -> Lam $ \y -> x
s :: Term a
s = Lam $ \f -> Lam $ \g -> Lam $ \x -> f # x # (g # x)
omega :: Term a
omega = (Lam $ \f -> f # f) # (Lam $ \f -> f # f)
run t = t :: Term String
main = do
print $ run $ s -- \a -> \b -> \c -> a(c)(b(c))
print $ run $ s # k # k -- \a -> a
-- print $ run $ omega -- bad idea
此外,不是编写这个Lam
,#
和东西,而是可以将lambda术语的字符串表示解析为HOAS - 这并不比打印HOAS术语更难。