List 一份名单;“无”;有价值吗?

List 一份名单;“无”;有价值吗?,list,haskell,algebraic-data-types,pattern-synonyms,List,Haskell,Algebraic Data Types,Pattern Synonyms,一些标准Haskell库是否定义了这样的数据类型 data ListWithEnd e a = Cons a (ListWithEnd e a) | End e 这是一个列表,其终止元素携带指定类型的值 因此ListWithEnd()同构于[],而ListWithEnd Void同构于无限流。或者,从不同的角度来看,ListWithEnd e a非常接近..我们可以将ListWithEnd定义如下: import Control.Monad.Free

一些标准Haskell库是否定义了这样的数据类型

data ListWithEnd e a = Cons a (ListWithEnd e a)
                     | End e
这是一个列表,其终止元素携带指定类型的值


因此
ListWithEnd()
同构于
[]
,而
ListWithEnd Void
同构于无限流。或者,从不同的角度来看,
ListWithEnd e a
非常接近..

我们可以将
ListWithEnd
定义如下:

import Control.Monad.Free

type LWE a e = Free ((,) a) e
我们通常期望抽象或泛型的表示应该以减少样板文件来奖励我们。让我们看看这个表示为我们提供了什么

在任何情况下,我们都将为cons案例定义一个模式同义词:

{-# LANGUAGE PatternSynonyms #-}

pattern x :> xs = Free (x, xs)
infixr 5 :>
我们可以映射、折叠和遍历末端元素:

fmap (+1) (0 :> Pure 0) == (0 :> Pure 1)
traverse print (0 :> Pure 1) -- prints 1
Applicative
实例为我们提供了非常简洁的连接:

xs = 1 :> 2 :> Pure 10
ys = 3 :> 4 :> Pure 20

xs *> ys          == 1 :> 2 :> 3 :> 4 :> Pure 20 -- use right end
xs <* ys          == 1 :> 2 :> 3 :> 4 :> Pure 10 -- use left end
(+) <$> xs <*> ys == 1 :> 2 :> 3 :> 4 :> Pure 30 -- combine ends
当然,我们可以利用iter

iter (uncurry (+)) (0 <$ xs) == 3 -- sum list elements
但在这一点上,我们可以考虑只编写普通ADT,并在几行代码中编写
应用程序
Monad
位可移动
实例。或者,我们可以使用
lens
并为列表元素编写
遍历

import Control.Lens

elems :: Traversal (LWE a e) (LWE b e) a b
elems f (Pure e)  = pure (Pure e)
elems f (x :> xs) = (:>) <$> f x <*> elems f xs

我没见过。也许(使用预定义函数时)定义
newtype list with end e a=LWE([a],e)
会更容易(wrt)试着用标准的东西来表达它,我想到了
type LWE a=Free((,)a)e
。你不能直接使用
([a],e)吗
?@OmarAntolín-Camarena:这不太一样,因为列表不必有结尾。特别是,
([a],Void)
将同构于
Void
,而不是无限流。@AndrásKovács您能将您的评论转换为答案,以便我能接受吗?
newtype LWE a e = LWE (Free ((,) a) e) deriving (lots of things)

instance Bifunctor LWE where bimap = bimapDefault
instance Bifoldable LWE where bifoldMap = bifoldMapDefault
instance Bitraversable LWE where bitraverse = ...
import Control.Lens

elems :: Traversal (LWE a e) (LWE b e) a b
elems f (Pure e)  = pure (Pure e)
elems f (x :> xs) = (:>) <$> f x <*> elems f xs
end :: Lens (LWE a e) (LWE a e') e e'
end f (Pure e)  = Pure <$> f e
end f (x :> xs) = (x :>) <$> end f xs