简体   繁体   English

Haskell 中的函数没有获取泛型类型参数

[英]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 8wrapped8box使用时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的预期参数匹配,因为IntBox a类型不匹配。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM