Haskell Lambdas和褶皱(左侧和右侧)

Haskell Lambdas和褶皱(左侧和右侧),haskell,lambda,functional-programming,Haskell,Lambda,Functional Programming,我真的不懂代码 myReverse'' :: [a] -> [a] myReverse'' xs = foldr (\x fId empty -> fId (x : empty)) id xs [] 如果: 空映射到[]关键是如何处理差异列表。让我们写出一些显式转换: type DList a = [a]->[a] emptyDList :: Dlist a emptyDList = id fromDList :: DList a -> [a] fromDList

我真的不懂代码

myReverse'' :: [a] -> [a]
myReverse'' xs = foldr (\x fId empty -> fId (x : empty)) id xs []
如果:


空映射到[]关键是如何处理差异列表。让我们写出一些显式转换:

type DList a = [a]->[a]

emptyDList :: Dlist a
emptyDList = id

fromDList :: DList a -> [a]
fromDList f = f []

myReverse'' :: ∀ a . [a] -> [a]
myReverse'' xs = fromDList $ foldr revCons emptyDList xs 
 where revCons :: a -> DList a -> DList a
       revCons x fId empty = fId $ x : empty

请注意,revCons有三个参数,尽管它的签名实际上只表明了两个:差异列表实际上是一种函数类型,但您可以将这些函数视为具体列表的抽象优化表示。

我喜欢理解这些带有foldr问题的反向列表的方式是将其拆分成若干部分,并运用这一经验教训。别担心,这并不像听起来那么可怕

首先,让我们注意到反向可以通过以下方式实现:

my_reverse xs = foldl (flip (:)) xs []
my_foldr :: (a -> (r -> r)) -> [a] -> (r -> r)
my_foldr f as = compose (map f as)
  where compose :: [r -> r] -> (r -> r)
        compose = foldr (.) id
这是我们问题的第一个简化:如果我们能够找出如何用foldr编写foldl,那么我们就可以将该解决方案插入my_reverse to并完成它

现在,foldr的标准类型签名如下:

但是参数的顺序其实并不重要,所以让我们以这种方式重新安排,同时加入一些隐式括号,我们将其与map进行比较:

一旦你看到这封信,不难看出我们可以这样写我的foldr:

my_reverse xs = foldl (flip (:)) xs []
my_foldr :: (a -> (r -> r)) -> [a] -> (r -> r)
my_foldr f as = compose (map f as)
  where compose :: [r -> r] -> (r -> r)
        compose = foldr (.) id
请按以下方式考虑:

映射操作将列表中的每个元素转换为我们应用于r值的转换步骤。 compose函数获取生成的步骤列表,并使用。操作人员 现在的诀窍是我们可以编写一个foldl对应物,只需稍加修改:

my_foldl :: (a -> (r -> r)) -> [a] -> (r -> r)
my_foldl f as = compose (map f as)
    where compose :: [r -> r] -> (r -> r)
          compose = foldr (flip (.)) id

{- Example:
>>>  my_foldl (:) [1..3] []
[3,2,1]
-}
我所做的只是改变。翻。!请注意,我的foldl是用map和foldr编写的。。。但地图也可以根据foldr重写:

因此,我们最终得到了一个不同于您试图理解的解决方案,并且比您试图理解的解决方案更长,但希望它能起到启发作用

如果您这样做:

Prelude :t \x fId empty -> fId (x : empty)
您将获得:

\x fId empty -> fId (x : empty) :: a -> ([a] -> t) -> [a] -> t
这里的函数类型相当于:

a -> ([a] -> t) -> ([a] -> t) 
这意味着一个接受两个参数的函数二进制函数。第二个参数是一个函数,即[a]->t,并返回一个函数,即[a]->t

此二进制函数与foldr采用的第一个参数匹配,即a->b->b

换句话说,foldr\x fId empty->fId x:empty接受两个参数:一个函数和一个列表,并返回一个函数

Prelude> :t foldr (\x fId empty -> fId (x : empty))
foldr (\x fId empty -> fId (x : empty))
  :: ([a] -> t) -> [a] -> [a] -> t
例如:foldr\x fId empty->fId x:empty id[1,2,3]

步骤1:3和id作为参数传递给匿名二进制函数。像\empty->ID3:empty这样的函数作为新的累加器值返回

步骤2:2和\empty->ID3:empty被传递给匿名二进制函数。并返回\empty->ID3:2:empty

步骤3:1和\empty->ID3:2:empty被传递给匿名二进制函数。并返回\empty->ID3:2:1:empty

因此foldr\x fId empty->fId x:empty id[1,2,3]生成一个类似\empty->id 3:2:1:empty的函数

如果您将\empty->ID3:2:1:empty应用于[],那么它将为您提供[3,2,1]


这意味着foldr\x fId empty->fId x:empty id[1,2,3][]产生[3,2,1]。

我可以对id为xs[]的图形排序/更改位置吗?你能澄清你的问题吗?很难理解你在问什么。我想我的_reverse xs=foldl flip:[]xs,末尾是[]xs,而不是。。。xs[]
Prelude :t \x fId empty -> fId (x : empty)
\x fId empty -> fId (x : empty) :: a -> ([a] -> t) -> [a] -> t
a -> ([a] -> t) -> ([a] -> t) 
Prelude> :t foldr (\x fId empty -> fId (x : empty))
foldr (\x fId empty -> fId (x : empty))
  :: ([a] -> t) -> [a] -> [a] -> t