List 一份名单;“无”;有价值吗?
一些标准Haskell库是否定义了这样的数据类型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
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