2015-09-07 79 views
6

我有一組lambda表達式,我將其傳遞給其他lambda表達式。所有的lambda只依賴於他們的論點,他們不會調用任何外部函數。當然,有時候它會讓人感到困惑,我會通過不正確的參數數量傳遞給另一個參數,從而創建一個GHCi異常。Haskell調試任意的lambda表達式

我想製作一個調試函數,它將採用任意lambda表達式(帶有未知數量的參數)並根據lambda的結構和函數返回一個字符串。

例如,假設我有以下lambda表達式:

i = \x -> x 
k = \x y -> x 
s = \x y z -> x z (y z) 

debug (s k)應該返回"\a b -> b"

debug (s s k)應該返回"\a b -> a b a"(如果我簡化是正確的)

debug s應該返回"\a b c -> a c (b c)"

Wha噸會是這樣做的好方法?

+1

不是真的在Haskell中,這種信息在編譯時被擦除。你可以使用模板haskell來實現它,但這並不簡單。 – bheklilr

+0

在那裏實現lambda演算有很多資源。 [TaPL](http://www.cis.upenn.edu/~bcpierce/tapl/)是一個特別好的項目,並且包括各種複雜程度的結石的實現。在Hackage上似乎也有一些小的實現,你可以使用它。 –

+0

Haskell是一種靜態類型語言。其實並不是深度涉及lambda微積分,除非lambda恰好是寫笛卡爾封閉類別表達式的有用方式。但直接使用類型來了解函數的作用,而不是查看一些等效的lambda表達式會更有效率。對於你想要達到的目標,像Scheme這樣的語言會更合適。 – leftaroundabout

回答

1

我認爲這樣做的方法是在Haskell中定義一個小的lambda微積分DSL(或使用現有的實現)。通過這種方式,而是採用原始Haskell配方,你會喜歡寫東西

k = Lam "x" (Lam "y" (App (Var "x") (Var "y"))) 
s = Lam "x" (Lam "y" (Lam "z" (App (App (Var "x") (Var "z") 
            (App (Var "y") (Var "z")))) 

,同樣爲si。這樣,你會寫/使用評估功能,讓你可以寫

debug e = eval e 
debug (App s k) 

這將使你在你自己的語法的最終形式。另外,您需要一種解釋器來將您的DSL語法轉換爲Haskell,以便您可以在代碼中實際使用這些函數。這可能不是你想到的東西(尤其是如果你需要對類型化語法進行評估的話),但我相信這會是一個很棒的工作。學習經驗。一個很好的參考將是chapter 6 of "Write you a Haskell"。使用現有的實現會容易得多(但不太好玩:))。

如果這僅僅是爲了調試的目的,您可以從ghc編譯的核心語法中獲益。請參閱chapter 25 of Real world Haskell,要使用的ghc標誌是-ddump-simpl。但是這意味着查看生成的代碼而不是在程序中生成表示。我也不確定在多大程度上能夠輕鬆識別Core代碼中的特定功能(我對YMMV沒有經驗)。

如果在函數中使用show會給出你描述的那種輸出,但是可能有很好的理由,函數不是Show的一個實例(我無法告訴你),這當然會很酷。

1

實際上,您可以通過利用模板哈斯克爾的漂亮打印來實現這一點,該模板與開箱即用的GHC一起提供。

首先,格式化功能應該在單獨的模塊中定義(這是一個TH限制):

module LambdaPrint where 

import Control.Monad 
import Language.Haskell.TH.Ppr 
import Language.Haskell.TH.Syntax 

showDef :: Name -> Q Exp 
showDef = liftM (LitE . StringL . pprint) . reify 

然後使用它:

{-# LANGUAGE TemplateHaskell #-} 
import LambdaPrint 

y :: a -> a 
y = \a -> a 
$(return []) --workaround for GHC 7.8+ 

test = $(showDef 'y) 

結果是或多或少可讀的,不計完全合格的名稱:

*Main> test 
"Main.y :: forall a_0 . a_0 -> a_0" 

這是怎麼回事上幾句話。 showDef是一個宏函數,用於從環境中提取某個名稱的定義並將其打印在字符串文字表達式中。要使用它,您需要引用lambda的名稱(使用')並將結果(它是帶引號的字符串表達式)拼接到某個表達式中(使用$(...))。

+0

我很抱歉,但我的解決方案似乎是錯誤的。變量聲明實際上並不包含其定義,所以'showDef'只顯示類型。這就是文件中關於這個機構的說法:「目前,這個價值是無關緊要的:返回RHS由於缺乏興趣而尚未實施。」 – Yuuri