String Haskell-Lambda褶皱
我有以下表示Haskell中Lambda演算的代数数据类型:String Haskell-Lambda褶皱,string,haskell,lambda,fold,algebraic-data-types,String,Haskell,Lambda,Fold,Algebraic Data Types,我有以下表示Haskell中Lambda演算的代数数据类型: data LExpr = Var String -- variable | App LExpr LExpr -- function application | Lam String LExpr -- Lambda abstraction deriving (Eq, Show) 我正在尝试构建附带的fold函数。我熟悉代数数据类型的一般折叠形式,它可以以这种方式呈现: f
data LExpr
= Var String -- variable
| App LExpr LExpr -- function application
| Lam String LExpr -- Lambda abstraction
deriving (Eq, Show)
我正在尝试构建附带的fold函数。我熟悉代数数据类型的一般折叠形式,它可以以这种方式呈现:
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
这是正确的方法吗?如果没有,我错在哪里以及如何修复它?我只提供一个提示 假设您有一个整数列表,类型如下:
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
。通过检查上面的列表中发生的情况
类型,您现在应该能够填充空格。查看您的签名,它与foldr
不同,您应该命名已更改的变量。还记得将构造函数括在括号中<例如,code>v f go e有类型String
,String->a
,LExpr->a
,和LExpr
,这是一个无意义的调用链。@Guvante ok那么签名对应什么?go(Var v)=v
,go(App e1 e2)=go e1 go++go e2和go(Lam ve)=v App go e
?我说得对吗?谢谢您的解释。@user4325010不,回想一下我们将Nil
映射到Nil
和Cons
映射到Cons
。所以Var
必须映射到。。。特别是Var v
必须映射到。。。v
go(Var v)=Var v
,go(App e1 e2)=App(go e1)(go e2)
,go(Lam v e)=Lam v(go e)
?对吗?@user4325010完美!