occ*_*lti 2 haskell tuples functor
在下面,我尝试使用fmap元组,但这不起作用,虽然它适用于列表和Just 4:
Prelude> fmap (+3) (Just 4)
Just 7
Prelude> fmap (+3) [1,2,3,4]
[4,5,6,7]
Prelude> fmap (+3) (10,11,12,13,14)
<interactive>:38:1: error:
* Non type-variable argument
in the constraint: Functor ((,,,,) a b1 c d)
(Use FlexibleContexts to permit this)
* When checking the inferred type
it :: forall a b1 c d b2.
(Num d, Num c, Num b1, Num a, Num b2, Functor ((,,,,) a b1 c d)) =>
(a, b1, c, d, b2)
Prelude>
Run Code Online (Sandbox Code Playgroud)
为什么fmap不适用于[5-]元组?
因为没有人增加了5元组Functor实例基础呢.如果你看一下base提供的Functor实例列表,你会发现Functor ((,) a),对的实例,但不是大型元组的实例,包括Functor ((,,,,) a b c d),这就是你需要的.
当然,跟进的问题是:为什么没有人增加了5元组Functor实例基础了吗?一个原因与必要性(或缺乏必然性)有关:在实践中,成对出现的次数远多于大型元组,并且随着元组变大,使用它们而不是非适合的非匿名类型变得越来越难以证明一个用例.既然如此,Functor对更大元组实例的需求并不是那么大.
虽然您没有提到您期望的行为Functor ((,,,,) a b c d),但值得注意的是fmap,对仅仅对第二个组件起作用,而较大元组的实例类似地仅处理最后一个组件.
GHCi> fmap not (False, True)
(False,False)
Run Code Online (Sandbox Code Playgroud)
其中两个原因是:
组件的类型可以是不同的,因此例如fmap not ("foobar", True)可能无法改变两个组件.
在编写实例时没有办法翻转类型构造函数,因此例如Functor,对于第一个组件上的对不能有一个实例(除非你使用newtype包装器,但除此之外).
虽然这种行为可能看起来令人惊讶,但如果您将类型(a, b)作为b带有注释(标记,标签,额外内容 - 但是您喜欢称之为附加内容)的值的对,则完全合理a.在这种情况下,您宁愿将其视为可以独立修改的两对值,您可以求助于Bifunctor该类:
GHCi> import Data.Bifunctor
GHCi> first reverse ("foobar", True)
("raboof",True)
GHCi> second not ("foobar", True)
("foobar",False)
GHCi> bimap reverse not ("foobar", True)
("raboof",False)
Run Code Online (Sandbox Code Playgroud)
(基础不提供Trifunctor,Tetrafunctor等等,由于缺乏需要,正如开头所讨论的那样.)
在提供Functor实例时,以相同的方式考虑更大的元组是合理的; 事实上,为了保持一致,这些实例可能存在.但是,有些人非常不喜欢对的实例,这导致建议将其他元组的实例添加到停止状态.
PS:或许值得一提的是,镜头库的(许多)用例之一是使用不是Functor作为仿函数的东西.这给了我们一个方便的方法来查看什么Functor和(如果那是一个东西)Pentafunctor实例将使用5元组:
GHCi> import Control.Lens
GHCi> over _5 (+3) (10,11,12,13,14)
(10,11,12,13,17)
GHCi> over _4 (+3) (10,11,12,13,14)
(10,11,12,16,14)
GHCi> over _3 (+3) (10,11,12,13,14)
(10,11,15,13,14)
GHCi> over _2 (+3) (10,11,12,13,14)
(10,14,12,13,14)
GHCi> over _1 (+3) (10,11,12,13,14)
(13,11,12,13,14)
Run Code Online (Sandbox Code Playgroud)
甚至有方法映射所有组件......
GHCi> over both (+3) (13,14)
(16,17)
GHCi> over each (+3) (10,11,12,13,14)
(13,14,15,16,17)
Run Code Online (Sandbox Code Playgroud)
......但是,毫不奇怪,他们要求所有组件具有相同的类型:
GHCi> over each (+3) (True,11,12,13,14)
<interactive>:9:12: error:
* No instance for (Num Bool) arising from a use of `+'
* In the second argument of `over', namely `(+ 3)'
In the expression: over each (+ 3) (True, 11, 12, 13, 14)
In an equation for `it':
it = over each (+ 3) (True, 11, 12, 13, 14)
Run Code Online (Sandbox Code Playgroud)
GHCi> :set -XPartialTypeSignatures
GHCi> :set -fno-warn-partial-type-signatures
GHCi> :t \f -> over each f :: (_,_,_,_,_) -> _
\f -> over each f :: (_,_,_,_,_) -> _
:: (w -> b5) -> (w, w, w, w, w) -> (b5, b5, b5, b5, b5)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
289 次 |
| 最近记录: |