Haskell Traversable1中的上下文边界

Haskell Traversable1中的上下文边界,haskell,Haskell,在包中,我找到了以下定义: class (Foldable1 t, Traversable t) => Traversable1 t where traverse1 :: Apply f => (a -> f b) -> t a -> f (t b) sequence1 :: Apply f => t (f b) -> f (t b) sequence1 = traverse1 id traverse1 f = sequence1 .

在包中,我找到了以下定义:

class (Foldable1 t, Traversable t) => Traversable1 t where
  traverse1 :: Apply f => (a -> f b) -> t a -> f (t b)
  sequence1 :: Apply f => t (f b) -> f (t b)

  sequence1 = traverse1 id
  traverse1 f = sequence1 . fmap f

为什么上下文边界设置为
Apply
(一个
Applicative
,没有
pure
),而不是
Functor
?显然,您需要覆盖其中一个定义,因此,使用“just”a
Functor
这是不可能的吗?

这只是一个稍微严格的
可遍历
——所有
可遍历1
都是
可遍历
,但反之亦然。关于为什么
Traversable
s需要
Applicative
s的更多细节,也许值得一看。从手势上讲,如果你有一个
函子,如果它包含很多值,就不可能对该函子的效果进行“排序”,因为你的“注入”函数
(a->fb)
是获得
b
s的唯一方法,你不能
加入
f
的层

但是,广义地说,当您定义可遍历的时,您只需要使用无效果注入函数,
pure
,作为“默认”值,这正是
Traversable1
所消除的。这就是为什么
NonEmpty
是一个实例,而
[]
不是

为了使事情具体化,考虑这些标识函数的实例实例,<代码>可能,<代码>非空列表,以及常规<代码> []/COD> < /P>

newtype Id a = Id a
instance Functor Id where fmap f (Id a) = Id (f a)

instance Applicative Id where
  pure = Id
  (Id f) <*> (Id x) = Id (f x)
我们需要
pure
来处理
Maybe
的“默认”
Nothing
情况(只比
Id
稍微复杂一点)

由于我们只使用了
()
,而不是
,所以我们可以将其作为
可遍历的1
实例

instance Traversable1 NonEmpty where
  traverse1 inj (NonEmpty a []) = (`NonEmpty` []) <$> inj a
  traverse1 inj (NonEmpty a (b: bs)) = 
    (\a' (NonEmpty b' bs') -> NonEmpty a' (b': bs')) 
    <$> inj a 
    <.> traverse1 inj (NonEmpty b bs)

编辑:最初我对
Traversable1 NonEmpty
的定义是轻描淡写的。目前的版本确实有效,但是眼睛更难看。以前我尝试过
遍历内部列表,这在精神上是有效的,因为
非空的
的第二个插槽中的
[]
有第一个插槽来帮助它,但这不能直接工作,因为内部列表有一个空的大小写
[]
,需要
。相反,我们必须通过在第一个位置“偷取”始终存在的
a
,然后在遍历后替换它来避免这种空情况

该方法(和数据类型定义)与半群和半群ID库本身中使用的版本非常相似,并且非常有用,因为它们可以利用常规
[]
后面的库动力,但是,如果我们对
非空
的定义稍有不同,我们就会发现
可遍历的
可遍历的1
之间存在大量的并行性。事实上,
Traversable1
实例可以存在,这确实是数据类型本身的一个特征——定义基本相同

import Data.Monoid
import qualified Data.Semigroup as Se
import Data.Traversable
import Data.Foldable
import Data.Semigroup.Foldable
import Data.Semigroup.Traversable
import Data.Functor.Apply
import Control.Applicative

-- For comparison
data List     a = Empty | List a (List     a)
data NonEmpty a = One a | Many a (NonEmpty a)

instance Functor NonEmpty where
  fmap f (One a) = One (f a)
  fmap f (Many a as) = Many (f a) (fmap f as)

instance Apply NonEmpty where
  (One f) <.> (One a)         = One (f a)
  (One f) <.> (Many a _)      = One (f a)
  (Many f _) <.> (One a)      = One (f a)
  (Many f fs) <.> (Many a as) = Many (f a) (fs <.> as)

instance Applicative NonEmpty where
  pure = One
  (<*>) = (<.>)

instance Foldable NonEmpty where
  foldMap f (One a) = f a
  foldMap f (Many a as) = f a <> foldMap f as

instance Foldable1 NonEmpty where
  foldMap1 f (One a) = f a
  -- Core distinction: we use the Semigroup.<> instead of the Monoid.<>
  foldMap1 f (Many a as) = f a Se.<> foldMap1 f as

instance Traversable NonEmpty where
  traverse inj (One a) = One <$> inj a
  traverse inj (Many a as) = Many <$> inj a <*> traverse inj as

instance Traversable1 NonEmpty where
  traverse1 inj (One a) = One <$> inj a
  traverse1 inj (Many a as) = Many <$> inj a <.> traverse1 inj as
导入数据.Monoid
导入限定数据。半群为Se
导入数据。可遍历
导入数据。可折叠
导入Data.Semigroup.Foldable
导入Data.Semigroup.Traversable
导入数据.Functor.Apply
导入控制
--作比较
数据列表a=空|列表a(列表a)
数据非空a=一个a |多个a(非空a)
实例函子非空,其中
fmap f(一个a)=一(一个)
fmap f(多个a为)=多个(f为)(fmap f为)
实例Apply非空,其中
(一个f)(一个a)=一个(f a)
(一个f)(多个a _)=一个(f a)
(多个f_u2;)(一个a)=一个(f a)
(多个f fs)(多个a as)=多个(f a)(fs as)
实例应用程序非空where
纯=一
() = ()
实例可折叠非空where
折叠图f(一个)=f a
折叠映射f(多个a)=f a折叠映射f a
实例Foldable1非空,其中
折叠贴图1 f(一个a)=f a
--核心区别:我们使用半群。而不是幺半群。
foldMap1 f(多a as)=f a Se。foldMap1 f as
实例可遍历非空where
横向输入(一个a)=一个输入a
导线输入(多个等于)=导线输入的多个等于
实例Traversable1非空,其中
导线1 inj(一个a)=一个inj a
traverse1 inj(多个a as)=多个a traverse1 inj as
data NonEmpty a = NonEmpty a [a]

instance Functor NonEmpty where fmap f (NonEmpty a as) = NonEmpty (f a) (fmap f as)

instance Apply NonEmpty where
  (NonEmpty f fs) <.> (NonEmpty x xs) = NonEmpty (f x) (fs <*> xs)

instance Pointed NonEmpty where
  point a = NonEmpty a []

instance Applicative NonEmpty where
  (<*>) = (<.>)
  pure = point

instance Traversable NonEmpty where
  traverse inj (NonEmpty a as) = NonEmpty <$> inj a <*> (traverse inj a as)
instance Traversable1 NonEmpty where
  traverse1 inj (NonEmpty a []) = (`NonEmpty` []) <$> inj a
  traverse1 inj (NonEmpty a (b: bs)) = 
    (\a' (NonEmpty b' bs') -> NonEmpty a' (b': bs')) 
    <$> inj a 
    <.> traverse1 inj (NonEmpty b bs)
instance Traversable [] where
  traverse _   []     = pure []
  traverse inj (x:xs) = (:) <$> inj x <*> traverse inj xs
import Data.Monoid
import qualified Data.Semigroup as Se
import Data.Traversable
import Data.Foldable
import Data.Semigroup.Foldable
import Data.Semigroup.Traversable
import Data.Functor.Apply
import Control.Applicative

-- For comparison
data List     a = Empty | List a (List     a)
data NonEmpty a = One a | Many a (NonEmpty a)

instance Functor NonEmpty where
  fmap f (One a) = One (f a)
  fmap f (Many a as) = Many (f a) (fmap f as)

instance Apply NonEmpty where
  (One f) <.> (One a)         = One (f a)
  (One f) <.> (Many a _)      = One (f a)
  (Many f _) <.> (One a)      = One (f a)
  (Many f fs) <.> (Many a as) = Many (f a) (fs <.> as)

instance Applicative NonEmpty where
  pure = One
  (<*>) = (<.>)

instance Foldable NonEmpty where
  foldMap f (One a) = f a
  foldMap f (Many a as) = f a <> foldMap f as

instance Foldable1 NonEmpty where
  foldMap1 f (One a) = f a
  -- Core distinction: we use the Semigroup.<> instead of the Monoid.<>
  foldMap1 f (Many a as) = f a Se.<> foldMap1 f as

instance Traversable NonEmpty where
  traverse inj (One a) = One <$> inj a
  traverse inj (Many a as) = Many <$> inj a <*> traverse inj as

instance Traversable1 NonEmpty where
  traverse1 inj (One a) = One <$> inj a
  traverse1 inj (Many a as) = Many <$> inj a <.> traverse1 inj as