Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 是否可以通过修改这个简单的缩减器来展示不同的评估策略?_Haskell_Lambda_Functional Programming_Lazy Evaluation_Lambda Calculus - Fatal编程技术网

Haskell 是否可以通过修改这个简单的缩减器来展示不同的评估策略?

Haskell 是否可以通过修改这个简单的缩减器来展示不同的评估策略?,haskell,lambda,functional-programming,lazy-evaluation,lambda-calculus,Haskell,Lambda,Functional Programming,Lazy Evaluation,Lambda Calculus,我是那种喜欢通过看代码而不是阅读冗长解释来学习的人。这可能是我不喜欢长篇学术论文的原因之一。代码是明确的,紧凑的,无噪音的,如果你没有得到一些东西,你可以用它玩-不需要问作者 这是Lambda演算的完整定义: -- A Lambda Calculus term is a function, an application or a variable. data Term = Lam Term | App Term Term | Var Int deriving (Show,Eq,Ord) --

我是那种喜欢通过看代码而不是阅读冗长解释来学习的人。这可能是我不喜欢长篇学术论文的原因之一。代码是明确的,紧凑的,无噪音的,如果你没有得到一些东西,你可以用它玩-不需要问作者

这是Lambda演算的完整定义:

-- A Lambda Calculus term is a function, an application or a variable.
data Term = Lam Term | App Term Term | Var Int deriving (Show,Eq,Ord)

-- Reduces lambda term to its normal form.
reduce :: Term -> Term
reduce (Var index)      = Var index
reduce (Lam body)       = Lam (reduce body)
reduce (App left right) = case reduce left of
    Lam body  -> reduce (substitute (reduce right) body)
    otherwise -> App (reduce left) (reduce right)

-- Replaces bound variables of `target` by `term` and adjusts bruijn indices.
-- Don't mind those variables, they just keep track of the bruijn indices.
substitute :: Term -> Term -> Term
substitute term target = go term True 0 (-1) target where
    go t s d w (App a b)             = App (go t s d w a) (go t s d w b)
    go t s d w (Lam a)               = Lam (go t s (d+1) w a) 
    go t s d w (Var a) | s && a == d = go (Var 0) False (-1) d t 
    go t s d w (Var a) | otherwise   = Var (a + (if a > d then w else 0))

-- If the evaluator is correct, this test should print the church number #4.
main = do
    let two = (Lam (Lam (App (Var 1) (App (Var 1) (Var 0)))))
    print $ reduce (App two two)

在我看来,上面的“reduce”函数更多地说明了Lambda演算,而不是一页页的解释,我希望我开始学习时能看看它。您还可以看到,它实现了一个非常严格的评估策略,甚至可以在抽象中使用。本着这种精神,如何修改该代码以说明LC可以拥有的许多不同的评估策略(按名称调用、延迟评估、按值调用、按共享调用、部分评估等)?按名称调用只需要一些更改:

  • 不评估lambda抽象的主体:
    reduce(Lam-body)=(Lam-body)

  • 不评估应用程序的参数。相反,我们应该将其替换为:

    reduce (App left right) = case reduce left of
        Lam body -> reduce (substitute right body)
    
  • 按需调用(也称为惰性求值)似乎更难(或者可能不可能)以完全声明的方式实现,因为我们需要记忆表达式的值。我看不出有什么办法可以通过微小的改变来实现这一目标

    共享调用不适用于简单的lambda演算,因为这里没有对象和赋值


    我们也可以使用完整的beta缩减,但是我们需要选择一些确定的评估顺序(我们不能选择一个“任意”的redex并使用我们现在的代码进行缩减)。这种选择将产生某种评估策略(可能是上述策略之一)

    这个话题相当广泛。我会写一些想法

    建议的
    reduce
    执行并行重写。也就是说,它将
    App t1 t2
    映射到
    App t1't2'
    (前提是
    t1'
    不是抽象)。有些策略,如CBV和CBN,更具有顺序性,因为它们只有一个redex

    为了描述它们,我将修改
    reduce
    ,以便它返回是否实际进行了缩减,或者该术语是否为标准形式。这可以通过返回一个
    可能的术语
    ,其中
    表示正常形式

    这样,CBN将是

    reduce :: Term -> Maybe Term
    reduce (Var index)            = Nothing   -- Vars are NF
    reduce (Lam body)             = Nothing   -- no reduction under Lam
    reduce (App (Lam body) right) = Just $ substitute right body
    reduce (App left right) = 
          (flip App right <$> reduce left) <|>  -- try reducing left
          (App left       <$> reduce right)     -- o.w., try reducing right
    
    reduce::Term->Maybe Term
    reduce(Var索引)=Nothing--Var是NF
    减少(林体)=无——林下无减少
    减少(应用程序(林体)右侧)=仅$替换右侧体
    减少(应用程序左/右)=
    (翻转应用程序右减左)--尝试左减
    (应用程序左减右)--o.w.,尝试右减
    
    而CBV将是

    reduce :: Term -> Maybe Term
    reduce (Var index)            = Nothing
    reduce (Lam body)             = Nothing   -- no reduction under Lam
    reduce (App (Lam body) right) 
         | reduce right == Nothing            -- right must be a NF
         = Just $ substitute right body
    reduce (App left right) = 
          (flip App right <$> reduce left) <|>
          (App left       <$> reduce right)
    
    reduce::Term->Maybe Term
    减少(Var指数)=无
    减少(林体)=无——林下无减少
    减少(应用程序(林体)右侧)
    |reduce right==Nothing--right必须是NF
    =仅需$替换右体
    减少(应用程序左/右)=
    (翻转应用程序右减左)
    (应用程序左减右)
    

    如果我没记错的话,懒散的评估(共享)不能用术语来表达。它需要图表来表示子项正在被共享。

    这是一个非常有趣的主题,尽管根据StackOverflow指南,我怀疑这个问题是否与主题有关。@leftaroundabout实际上,我也有一些疑问。然而,我认为这可以被看作是一个编程问题,因为底部的问题是关于如何调整代码以适应多种策略(可能以优雅的方式)。这不仅仅是关于lambda演算。