Haskell 数据类型的应用实例
我正在尝试为我的数据类型编写Applicative实例Haskell 数据类型的应用实例,haskell,Haskell,我正在尝试为我的数据类型编写Applicative实例 data Multinode k v = Multinode { key :: k , values :: [v] } deriving Show data Multimap k v = Multimap [Multinode k v] deriving Show 我还在学哈斯克尔。所以我可能会犯一些有趣的错误。如
data Multinode k v = Multinode { key :: k
, values :: [v]
} deriving Show
data Multimap k v = Multimap [Multinode k v] deriving Show
我还在学哈斯克尔。所以我可能会犯一些有趣的错误。如果我理解正确,Applicative是函子的子集。必须定义的运算符是pure
和
pure::a->fa
()::f(a->b)->f a->f b
我的尝试如下
instance Applicative (Multimap k) where
pure x = Multimap [(Multinode x [x])]
(Multimap mf@((Multinode kf vsf):nsf)) <*> (Multimap mx@((Multinode kx vsx):nsx)) =
Multimap [Multinode kf (vsf <*> vsx)]
实例应用程序(Multimap k),其中
纯x=多映射[(多节点x[x])]
多映射mf@((多节点kf-vsf):nsf))(多映射mx@((多节点kx-vsx):nsx))=
多映射[多节点kf(vsf vsx)]
贴图和多重贴图自然不适用。原因如下:你需要
pure
:: (...) -- Possible constraint involving k, but not v
=> v -> MultiMap k v
由于对v
没有约束,pure
无法使用其参数生成任何键。因此,结果中的键集必须始终相同,这对于我所知道的任何有意义的
概念来说都是行不通的
semigroupoids
包提供了一个名为的类,它更有前途:
class函子f=>Apply f其中
()::f(a->b)->f a->f b
liftF2::(a->b->c)->f a->f b->f c
(.>)::f a->f b->f b
(f b->f a
这与
Applicative
类似,但没有pure
,
类似于
,liftF2
类似于liftA2
,等等。半群体
包包含一个实例Ord k=>Apply(映射k)
。您应该能够根据您的类型的一般想法,为您的类型想出几个不同的实例。贴图和多重贴图自然不适用于应用程序。
。原因如下:您需要
pure
:: (...) -- Possible constraint involving k, but not v
=> v -> MultiMap k v
由于对v
没有约束,pure
无法使用其参数生成任何键。因此结果中的键集必须始终相同,这对于我所知道的任何有意义的
概念都不起作用
semigroupoids
包提供了一个名为的类,它更有前途:
class函子f=>Apply f其中
()::f(a->b)->f a->f b
liftF2::(a->b->c)->f a->f b->f c
(.>)::f a->f b->f b
(f b->f a
这与
Applicative
类似,但没有pure
,
类似于
,liftF2
类似于liftA2
,等等。半群体
包包含一个实例Ord k=>Apply(映射k)
。你应该能够根据你的类型的一般想法为你的类型想出几个不同的实例。那么,当你尝试这样做时会发生什么呢?就应用程序而言,只有具有一个自由类型参数的类型构造函数才能成为它的实例;实际上你正在制作多映射k
,而不是Multimap是它的一个实例。但是,您的纯实现强制v
成为[k]
对于多节点
,以及作为结果的多映射
。我认为这不是故意的。也许你只需要想一想。也许还需要澄清问题。你应该编辑以使你的问题明确。你会得到错误或意外的结果吗?通常,映射类型可以是应用性的
可以有一个“默认”值,例如data M k v=M v[N k v]
。如果希望fx
将f
中的每个函数应用于x
中同一个键的每个值,那么因为身份法则要求pure id m
=m
,pure id
必须将每个键映射到id
。这就像ZipList
,其中pure x=ZipList(重复x)
,类似于带有自然数键(列表索引)的地图。请参阅。@JonPurdy可以有“默认”值的地图类型将是data M k v=M(可能是v)[N k v]
,不是吗。@威尔斯:哦,一点也不,我只是很傻,如果我被认为是个小淘气,很抱歉。你提出了一个很好的观点:一个不能为空的映射有点奇怪!有一些折衷。正如我在我的链接答案中提到的,你可以通过为v
参数(m@K)传递一个可能包装的类型来恢复空映射@(可能是V)
),这相当于“非总查找”(Kleisli可能是kv
)和“可选值的总查找”(Kleisli标识K(可能是V)
)之间的差异那么,当您尝试这样做时会发生什么呢?就Applicative
而言,只有具有1个自由类型参数的类型构造函数才能成为它的实例;实际上,您正在使Multimap k
,而不是Multimap
成为它的实例。然而,pure
的实现迫使v
成为它的实例[k]
对于多节点
,以及作为结果的多映射
。我认为这不是故意的。也许你只需要想一想。也许还需要澄清问题。你应该编辑以使你的问题明确。你会得到错误或意外的结果吗?通常,映射类型可以是应用性的
可以有一个“默认”值,例如data M k v=M v[N k v]
。如果希望fx
将f
中的每个函数应用于x
中同一个键的每个值,那么因为身份法则要求pure id m
=m
,pure id
必须将每个键映射到id
。这就像ZipList
,其中pure x=ZipList(重复x)
,类似于带有自然数键(列表索引)的地图。请参阅。@JonPurdy可以有“默认”值的地图类型将是data M k v=M(可能是v)[N k v]
,不是吗。@威尔斯:哦,一点也不,我只是在傻,如果我被认为是个小淘气,那就很抱歉了。你提出了一个很好的观点:一张不能为空的地图有点奇怪!有一些折衷。