了解(可流通产品)类型

时间:2019-02-14 12:34:44

标签: haskell

fp-course中获得以下信息:

data Product f g a =
  Product (f a) (g a)

class Functor f where
  -- Pronounced, eff-map.
  (<$>) ::
    (a -> b)
    -> f a
    -> f b

class Functor f => Applicative f where
  pure ::
    a -> f a
  (<*>) ::
    f (a -> b)
    -> f a
    -> f b

我尝试为Traversable定义Product f g a实例:

instance (Traversable f, Traversable g) =>
  Traversable (Product f g) where
  traverse :: 
    Applicative h =>
    (a -> h b)
    -> Product f g a
    -> h (Product f g b)  
  traverse fn (Product fa ga) = Product (traverse fn fa) (traverse fn ga)

编译器显示错误:

src/Course/Traversable.hs:106:33: error:
    • Occurs check: cannot construct the infinite type: h ~ Product h h
      Expected type: h (Product f g b)
        Actual type: Product h h (f b)

我了解我的定义有误,但我不了解实际类型为Product h h (f b)

我相信Product (traverse fn fa) (traverse fn ga)的类型是:

Product (h (f b)) (h (g b))

因为traverse的签名是Applicative f => (a -> f b) -> t a -> f (t b)

g的实际类型在哪里Product h h (f b)?请解释上面的实际类型。

1 个答案:

答案 0 :(得分:4)

是的。你有

traverse :: (a -> h b) -> f a -> h (f b)
traverse    fn            fa  :: h (f b)   -- and,

traverse :: (a -> h b) -> g a -> h (g b)
traverse    fn            ga  :: h (g b)

因此

Product (traverse fn fa)  (traverse fn ga) :: Product h h (f b)
        (h        (f b))  (h        (g b))

强制使用等效项f b ~ g bf ~ g ,因为Product p q t被定义为

Product (p        t    )  (q        t    )
------------------------------------------
       p ~ h   t ~ f b    q ~ h    t ~ g b

因此,将Product应用于两个traverse的结果并没有成功。

但是两者的类型分别为h (f b)h (g b),并且h是一个Applicative,我们试图创建类型为h (Product f g b)并带有 h 的内部键入,所以只要我们能

         h (f b)           h (g b)              h r              h s
        ---------------------------            ----------------------
         h (Combined  (f b)  (g b))             h (Combined   r    s)

,事实上,由于两个b是相同的,

        ---------------------------
         h (Combined   f      g b )

因此,我们想从foo :: r -> s -> t中获取bar :: h r -> h s -> h t ...如果只有such a function ...

baz :: (Applicative h) => (r -> s -> t) -> (h r -> h s -> h t)

...,答案是liftA2 Product (traverse fn fa) (traverse fn ga),将数据构造函数Product应用于两个遍历的内部结果“ in” “ inside” ”(位于“ ”的幕后)

         h r       h s
           r   ->    s   ->   t
        ------------------------
         h                    t