[英]Function in Haskell not getting generic type parameter
In Haskell I have the following在 Haskell 中,我有以下内容
data Box a = Box a deriving Show
instance Functor Box where
fmap func (Box a) = Box (func a)
box :: Box Int
box = Box 8
wrapped :: Box (Box Int)
wrapped = Box <$> box
unwrap :: (Box a) -> a
unwrap (Box val) = val
In GHCi I can call fmap
with unwrap wrapped
and I get Box 8
, which I would expected.在 GHCi 中,我可以使用fmap
unwrap wrapped
调用fmap
并得到Box 8
,这是我所期望的。
*Main> fmap unwrap wrapped
Box 8
When I call fmap
with unwrap box
I get error about the types not matching, but I was thinking I would get the value 8.当我用fmap
unwrap box
调用fmap
,我收到关于类型不匹配的错误,但我想我会得到值 8。
*Main> fmap unwrap box
<interactive>:26:13: error:
• Couldn't match type ‘Int’ with ‘Box b’
Expected type: Box (Box b)
Actual type: Box Int
• In the second argument of ‘fmap’, namely ‘box’
In the expression: fmap unwrap box
In an equation for ‘it’: it = fmap unwrap box
• Relevant bindings include
it :: Box b (bound at <interactive>:26:1)
I would have expected fmap unwrap box
would give the value 8
.我原fmap unwrap box
会给出值8
。
How would I define unwrap
to be able to get the value of Box 8
for wrapped
and 8
for box
when using fmap
?我如何定义unwrap
,以便能够获得的价值Box 8
的wrapped
和8
对box
使用时fmap
?
I do not think it matters but I am using GHCi version 8.8.4我不认为这很重要,但我使用的是 GHCi 8.8.4 版
If you have a box = Box 8
and want to get a plain 8
, you should just call unwrap box
, not fmap unwrap box
.如果你有一个box = Box 8
并且想要一个普通的8
,你应该只调用fmap unwrap box
unwrap box
,而不是fmap unwrap box
。 In general, fmap
will never let you unwrap a value because its type (Functor f) => (a -> b) -> fa -> fb
specifies that the result of fmap xy
will have the wrapped type fb
.一般来说, fmap
永远不会让你解包一个值,因为它的类型(Functor f) => (a -> b) -> fa -> fb
指定fmap xy
的结果将具有包装类型fb
。 Let's walk through the types to see why this happens:让我们来看看这些类型,看看为什么会发生这种情况:
When we call fmap unwrap
, we can "unify" the type of unwrap
with the type of the first argument to fmap
, which gives us this specialized type for fmap
:当我们调用fmap unwrap
,我们可以通过“统一”的类型unwrap
与第一个参数的类型fmap
,这给了我们这种特殊类型的fmap
:
fmap :: (Functor f) => (a -> b) -> f a -> f b
unwrap :: Box a -> a
fmap :: (Functor f) => (Box a -> a) -> f (Box a) -> f a
Notice that because f
doesn't appear in the type of the first argument of fmap
, Box
doesn't fill in for f
.请注意,因为f
没有出现在fmap
的第一个参数的fmap
,所以Box
不会填充f
。 We can then apply unwrap
to this specialized version of fmap
:然后,我们可以将unwrap
对这个特殊版本fmap
:
fmap unwrap :: (Functor f) => f (Box a) -> f a
This is almost certainly not the type you're expecting here.这几乎肯定不是您在这里期望的类型。 When we unify this for the argument Box (Box 8)
, we get the specialized type:当我们将其统一为参数Box (Box 8)
,我们得到专门的类型:
fmap unwrap :: (Functor f) => f (Box a ) -> f a
Box (Box 8) :: Box (Box Int)
fmap unwrap :: Box (Box Int) -> Box Int
But when we try to unify this with the type of argument Box 8
, we run into a problem:但是当我们尝试将其与参数Box 8
的类型统一时,我们遇到了一个问题:
fmap unwrap :: (Functor f) => f (Box a) -> f a
Box 8 :: Box Int
I can't match the type of Box 8
with the expected argument to fmap unwrap
because Int
doesn't match the type Box a
.我无法将Box 8
的类型与fmap unwrap
的预期参数匹配,因为Int
与Box a
类型不匹配。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.