Haskell 隐式提升的正确性

Haskell 隐式提升的正确性,haskell,types,Haskell,Types,假设我有一个在monad上通用的值: m :: (Monad m) => m A -- 'A' is some concrete type 现在让我们假设我以两种不同的方式将此值专门化为一个具体的monad transformer堆栈: m1 :: T M A m1 = m m2 :: T M A m2 = lift m 。。。其中M和tm是单子,而T是单子转换器: instance Monad M where ... instance (Monad m) => Monad

假设我有一个在monad上通用的值:

m :: (Monad m) => m A  -- 'A' is some concrete type
现在让我们假设我以两种不同的方式将此值专门化为一个具体的monad transformer堆栈:

m1 :: T M A
m1 = m

m2 :: T M A
m2 = lift m
。。。其中
M
tm
是单子,而
T
是单子转换器:

instance Monad M where ...
instance (Monad m) => Monad (T m) where ...
instance MonadTrans T where ...
。。。这些实例遵循单子定律和单子变换定律

我们能否推断:

m1 = m2
。。。除了它的类型之外,对
m
一无所知

这只是一种冗长的方式,询问
lift m
是否是
m
的有效替代品,假设两种类型都进行了检查。这个问题的措辞有点困难,因为它需要在替换前后将
m
类型检查作为两个单独的单子。据我所知,这种替换进行类型检查的唯一方法是如果
m
在monad上是泛型的


我模糊的直觉是,替换应该总是正确的,但我不确定我的直觉是否正确,或者如何证明它是否正确。

如果
m::Monad m=>ma
,那么
m
对于某些
x::A
,必须等价于
返回x
,因为获得任何东西的唯一方法是:mx返回
(>>=)
。但是为了使用
(>>=)
,您必须能够生成一些
my
,您可以使用
返回
,或者使用
(>=)
的另一个应用程序。无论哪种方法,最终都必须使用
return
,monad定律保证整个表达式将等价于
returnx

(如果
m
在monad上是完全多态的,那么您必须能够在
m~Identity
上使用它,因此它不能使用任何奇特的monad技巧,除非您向它传递一个参数。使用这种技巧,例如和。)

考虑到
m=return x
,我们通过monad变压器定律(
lift.return=return
)知道
lift m=m

当然,这只适用于这种特殊类型。例如,如果您有
m::MonadState S m=>ma
,那么
m
很容易与
lift m
不同——例如,对于类似
StateT A(State A)A
的类型,
get
lift get
将不同


(当然,所有这些都被忽略了⊥. 再说一次,如果你不遵守,大多数单子无论如何都不遵守法律。)

我认为这是一个草率的说法,你的
m
等同于
lift m

我认为我们必须尝试证明关于
m
(或者更确切地说,关于
(Monad m)=>ma
类型的所有可能值)的一些东西。如果我们认为<代码> Monad <代码>仅由绑定和返回组成,而忽略底部和<代码>失败<代码>,那么您的<代码> m <代码>必须在顶层是:

mA = return (x)
mB = (mX >>= f)
对于
mA
而言,
m
的两种形式根据monad变压器定律是等效的:

lift (return (x)) = return (x)
这是基本情况。然后我们剩下第二个变压器定律来解释
mB

lift (mX >>= f) = lift mX >>= (lift . f)
我们想证明我们的
mB
等于这个扩展:

mX >>= f = lift mX >>= (lift . f)
我们假设bind的左侧是等价的(
mX=liftmx
),因为这是我们的归纳假设(右?)

那么我们剩下来证明
f=lift。f
通过计算f
的外观:

f :: a -> m b
f = \a -> (one of our forms mA or mB)
lift。f
看起来像:

f = \a -> lift (one of our forms mA or mB)
这让我们回到了我们的假设:

m = lift m

这是“参数证明”,可以用形式表示。你的论点很好。当然,这只是一个草图。顺便说一下,我应该注意到我忽略了
fail
。在出现
fail
的情况下,
m
lift m
的行为可能会有所不同。(并不是说有任何
fail
法则,就其本身而言……但是对于
mtl
中的实际monad变压器,您可以做一个反例。)我特别感兴趣的是对参数治疗的解释,原因是我脑子里有一个关于管道的更复杂的问题。如果你或@PhilipJF解释说我会接受这个答案,@GabrielGonzalez shachaf以30秒的优势击败了我,那么你对我的答案有何反应?我也很想看到更有经验的人构造一个证明,或者回应我的尝试,这样我就可以从所有这些中学到一些东西too@jberryman你的答案和我的非常相似,这就是为什么我投了赞成票,但我想找一些真正优雅和一般的东西,因为我想把这条推理路线推广到管道上。