【发布时间】:2015-02-26 08:12:58
【问题描述】:
我创建了这个类型类以使 Divisible 函子(“Applicative 的逆变模拟”-https://hackage.haskell.org/package/contravariant-1.2/docs/Data-Functor-Contravariant-Divisible.html)可用于具有多个参数的函数,其方式与 Applicative 函子非常相似。
这个想法是你写unFunc |$| fa |*| fb |*| fc,其中:
unFunc :: z -> (a, (b, (c, ())))
fa :: f a
fb :: f b
fc :: f c
得到一个f z,对于一些Divisible函子f。 |$| 是来自Data.Functor.Contravariant.Divisible 的divide,|*| 是来自我下面的代码的dApply:
{-# LANGUAGE FlexibleContexts
, FlexibleInstances
, FunctionalDependencies
, MultiParamTypeClasses
, TypeFamilies
, UndecidableInstances
#-}
import Control.Applicative ((<$>), (<*>), Applicative)
import Data.Functor.Contravariant.Divisible
( Divisible(divide, conquer)
, divided
)
result :: (b -> c) -> (a -> b) -> (a -> c)
result = fmap
class Divisible f => DivisibleApply f t z r | f t z -> r, r t -> f, r t -> z
where dApply :: (f (a, t) -> f z) -> f a -> r
instance Divisible f => DivisibleApply f () z (f z)
where dApply = (. flip divided conquer)
instance DivisibleApply f b z r' => DivisibleApply f (a, b) z (f (a, b) -> f z)
where dApply = flip (result.result) divided
这确实有效!但是DivisibleApply 类似乎太复杂了。我实际上只是在t 参数上“切换”,我实际上希望在f 和z 中完全多态;它们只是类参数,因为实例需要根据它们实例化 r。
最初我尝试使用类型族;该类只有一个参数t,而r 的角色由关联类型承担。我遇到的问题(以及许多其他变体)是,即使我可以让它接受类和实例,将它应用于多个参数时也会因类型变量不明确而失败。我相信这是因为我没有与haskell 沟通我一直使用相同的f。
是否有可能在保持unFunc |$| fa |*| fb |*| fc 用法的同时恢复dApply 的更简单类型?
(我的最终目标是使用它来创建一个包含 both Applicative 和 Divisible 的类型类;给定一对函数 func :: a -> b -> c -> z 和 unFunc :: z -> (a, (b, (c, ()))) 应该是可能的制作一个函数f a -> f b -> f c-> f z 只知道f 是协变的或逆变的,却不知道是哪个。因此我为什么要镜像Applicative 用法的结构)
【问题讨论】:
-
您最终是否使用关联类型lpaste.net/6307517597139075072 尝试了这种变体?
-
@aavogt 很确定这与我的第一次尝试相同,是的。问题是
dApply的中间应用程序产生了模棱两可的类型变量错误,即使完全指定了最终结果的类型 -
unFunc |$| fa |*| fb |*| fc是否足以在您的情况下触发它,或者您是否正在使用其他东西进行测试? fwiw,通过我的粘贴,ghci 可以推断出unFunc |$| fa |*| fb |*| fc :: Divisible f => f a -
@aavogt 嗯,等我准备好我的开发机器后,我会试一试。也许有一些我没有发现的不同之处。
-
@aavogt 这可以完美地回答这个问题。我不知道我是怎么错过的;我想可能当我尝试这么简单的事情时,我仍然在尝试直接实现我的组合 Applicative/Divisible 类,并且在那种情况下得到了我正在谈论的那种模棱两可的类型变量错误。如果你想回答这个问题,我会接受。
标签: haskell typeclass contravariance