2015-06-14 90 views
4

我代表演算哈斯克尔以下代数数据类型:哈斯克尔LAMBDA倍

data LExpr 
    = Var String   -- variable 
    | App LExpr LExpr -- function application 
    | Lam String LExpr -- Lambda abstraction 
    deriving (Eq, Show) 

我试图建立与之相适应折叠功能。我与一般的折叠形式代数数据类型,它可以是这样的方式存在认识:

foldr :: (α -> β-> β) -> β -> [α] -> β 
foldr (#) z = go 
    where 
    go []  = z 
    go (x:xs) = x # go xs 

所以,我迄今所做的:

lfold :: (String -> a) -> (a -> a -> a) -> (String -> a -> a) -> LExpr -> a --given by definition 
lfold f z = go 
    where 
    go (Var _) = z   --Not sure here how to do the base case 
    go (Lam v e) = v f go e 

这是正确的方法是什么?如果不是,我错了,如何解决它?

+0

看看你的签名,它与'foldr'不同,你应该命名变化的变量。还要记住用圆括号包装你的构造函数。例如'v f go e'的类型为'String','String - > a','LExpr - > a'和'LExpr',这是一个无意义的调用链。 – Guvante

+0

@Guvante确定那么对应的签名是什么? – user8

+1

http://stackoverflow.com/questions/16426463/what-c​​onstitutes-a-fold-for-types-other-than-list –

回答

1

我只会提供提示。

假设你有一列整数类型,如下所示:

data List = Nil | Cons Int List 

然后,折变成

foldr :: β -> (α -> β -> β) -> [α] -> β 
foldr nil cons = go 
    where 
    go Nil   = nil 
    go (Cons x xs) = cons x (go xs) 

注意的是,一旦我仔细命名参数nil, cons那么它只是一个事1)将Nil(构造函数)映射到nil(参数),2)将Cons映射到cons,3)将go应用于List类型的子项(即,即,xs)。

你的类型,

data LExpr 
    = Var String   -- variable 
    | App LExpr LExpr -- function application 
    | Lam String LExpr -- Lambda abstraction 

我们可以用同样的伎俩:

lfold :: (String -> a) -> (a -> a -> a) -> (String -> a -> a) -> LExpr -> a 
lfold var app lam = go 
    where 
    go (Var v)  = ?? 
    go (App e1 e2) = ?? 
    go (Lam v e) = ?? 

注意我是如何命名的三个参数:var, app, lam。通过检查上述List类型中发生的情况,您现在应该可以填写空白。

+0

'go(Var v)= v','go(App e1 e2)= go e1 ++ go e2'和'go(Lam ve)= v app go e'?我对吗?并感谢您的解释。 – user8

+1

@ user4325010不,回想一下,我们将'Nil'映射到'nil'和'Cons'映射到'cons'。所以'Var'必须映射到...特别是'Var v'必须映射到'... v'。 – chi

+1

'go(Var v)= var v','go(App e1 e2)= app(go e1)(go e2)','go(Lam v e)= lam v(go e)'?对? – user8