为什么`(fmap.fmap)中的类型总和只是[1,2,3]`工作?

时间:2017-12-08 15:44:57

标签: haskell

我正在享受我生命中的时间阅读精彩的Haskell Programming from first principles而我是通过以下示例来实现的,我只是无法拆开(Page 1286电子阅读器):

override func viewDidLoad() {
    super.viewDidLoad()

    let youtubeURL = URL(string: "https://www.youtube.com/embed/KUh2O8HylUM")
    let request = URLRequest(url: youtubeURL!)

    videoPlayer.load(request)
    // Do any additional setup after loading the view.
}

我很明显以下是如何工作的:

Prelude> (fmap . fmap) sum Just [1, 2, 3]
Just 6

我已经手动解构Prelude> fmap sum $ Just [1,2,3] Just 6 以了解这些类型的工作原理。但是当把它想象为“两次提升”时,它没有意义,因为我正在解除Just和List数据构造函数。

我在(fmap . fmap)中输入了以下内容:

ghci

我不明白如何派生最后的输出。在向Prelude> :t (fmap . fmap) (fmap . fmap) :: (Functor f, Functor f1) => (a -> b) -> f1 (f a) -> f1 (f b) Prelude> :t (fmap . fmap) sum (fmap . fmap) sum :: (Num b, Foldable t, Functor f, Functor f1) => f1 (f (t b)) -> f1 (f b) Prelude> :t (fmap . fmap) sum Just (fmap . fmap) sum Just :: (Num b, Foldable t) => t b -> Maybe b 数据构造函数提供(fmap . fmap) sum时,编译器如何知道为Just替换f1f?在我得到一个好的答案之后,我怎么能自己弄明白呢?

2 个答案:

答案 0 :(得分:6)

这不会解除MaybeList(具有类型问题的(fmap . fmap) sum (Just [1,2,3])),但会超过函数类型(->)和{ {1}}。

Maybe

答案 1 :(得分:6)

如果您不理解特定答案的工作原理,请将您提供的参数与上一步中的类型对齐。

Prelude> :t (fmap . fmap) sum
(fmap . fmap) sum
  :: (Functor f, Functor f1, Num b) => f (f1 [b]) -> f (f1 b)

因此,为了完成这项工作,Just必须包含f (f1 [b])类型,然后(fmap . fmap) sum Just必须包含f (f1 b)类型。

Just :: (Functor f, Functor f1, Num b) => f (f1 [b])

ff1应该在这里不明显,所以让我们试试RHS吧。我们可以作弊并要求GHCi检查(fmap . fmap) sum Just的实际值应该是什么:

Prelude> :t (fmap . fmap) sum Just
(fmap . fmap) sum Just :: Num b => [b] -> Maybe b

但是这个匹配:

(Functor f, Functor f1, Num b) => f (f1 b)

我们正试图找出ff1在这里的内容。所以我们必须稍微重写一下,以便它具有相同的结构(请记住,->是语法糖并且有时会妨碍):

(fmap . fmap) sum Just :: Num b => [b] -> Maybe b
-- Same as...
(fmap . fmap) sum Just :: Num b => (->) [b] (Maybe b)
-- Or...
(fmap . fmap) sum Just :: Num b => ((->) [b]) (Maybe b)
--                     Functor f = ((->) [b])
--                                Functor f1 = Maybe

所以我们可以弄清楚,为了匹配类型,Functor f必须是(->) [b] ...请记住函数也是函子! Functor f1Maybe,这有点明显。

我们可以测试一下:

Prelude> :t (fmap . fmap) sum :: Num b => ([b] -> Maybe [b]) -> ([b] -> Maybe b)
(fmap . fmap) sum :: Num b => ([b] -> Maybe [b]) -> ([b] -> Maybe b)
  :: Num b => ([b] -> Maybe [b]) -> [b] -> Maybe b

GHCi认为它的类型检查很好。

这里唯一容易忘记的部分就是(->) [b]是一个有效的函子!