这可能是微不足道的,但我不明白以下是什么意思。
instance Functor Identity where
fmap = coerce
所以,我可以尝试定义类似的东西:
Prelude Control.Lens Data.Functor.Identity> :t fmap
fmap :: Functor f => (a -> b) -> f a -> f b
Prelude Control.Lens Data.Functor.Identity> let z f g = coerce f g
Prelude Control.Lens Data.Functor.Identity> :t z
z :: Contravariant ((->) t) => (t -> a) -> t -> b
但是,用简单的术语来表达什么意思?
答案 0 :(得分:7)
class DeadlockTest extends TestKit(ActorSystem()) with FunSuiteLike {
test("deadlock attempt") {
val b = TestProbe()
val a = TestActorRef(new Actor {
override def preStart() = b.ref ! "pre"
def receive = {
case msg =>
sender ! msg
context.stop(self)
}
})
b.watch(a)
b.send(a, "foo")
b.expectMsg("pre")
b.expectMsg("foo")
b.expectTerminated(a)
b.unwatch(a)
}
}
的使用在GHC 7.10中是新的,并且是为了提高效率而完成的。 “真正的”定义是
coerce
fmap :: (a -> b) -> (Identity a -> Identity b)
fmap f (Identity a) = Identity (f a)
构造函数的包装/解包应该在编译时进行优化,但似乎Identity
开发人员有理由确保使用{{1}不会降低性能}。
我们可以使用base
的原因是coerce
与coerce
同构(同一),因此我们可以强制Identity a
到a
恰好是专门针对a -> b
的{{1}}的定义!
答案 1 :(得分:5)
您在哪里找到Identity
的仿函数实例?这是我在Data.Functor.Identity
中找到的那个:
newtype Identity a = Identity { runIdentity :: a }
instance Functor Identity where
fmap f m = Identity (f (runIdentity m))
但至于它做了什么......它绝对没有,而且这是故意的。 fmap f (Idendity x)
与Idendity (f x)
相同。它只是将函数应用于它包含的值。
为什么你想要一个没有做任何事情的算子?如果你的函数需要一个仿函数,但你只有一个常规的非仿函数值,你可以将你的值包装在Identity
中并传入它并且它会表现正常。它基本上只是为了满足类型检测器的一层包装。