Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 为什么可以';延续monad不存在MonadFix的实例吗?_Haskell_Monads_Continuation_Monadfix - Fatal编程技术网

Haskell 为什么可以';延续monad不存在MonadFix的实例吗?

Haskell 为什么可以';延续monad不存在MonadFix的实例吗?,haskell,monads,continuation,monadfix,Haskell,Monads,Continuation,Monadfix,我们怎样才能证明它没有有效的实例呢?事实上,这并不是说不可能有一个MonadFix实例,只是库的类型有点太受限了。如果您在所有可能的rs上定义ContT,那么不仅MonadFix成为可能,而且在Monad之前的所有实例都不需要基础函子: newtype ContT m a = ContT { runContT :: forall r. (a -> m r) -> m r } instance Functor (ContT m) where fmap f (ContT k) = C

我们怎样才能证明它没有有效的实例呢?

事实上,这并不是说不可能有一个
MonadFix
实例,只是库的类型有点太受限了。如果您在所有可能的
r
s上定义
ContT
,那么不仅
MonadFix
成为可能,而且在
Monad
之前的所有实例都不需要基础函子:

newtype ContT m a = ContT { runContT :: forall r. (a -> m r) -> m r }
instance Functor (ContT m) where
  fmap f (ContT k) = ContT (\kb -> k (kb . f))
instance Monad (ContT m) where
  return a = ContT ($a)
  join (ContT kk) = ContT (\ka -> kk (\(ContT k) -> k ka))
instance MonadFix m => MonadFix (ContT m) where
  mfix f = ContT (\ka -> mfixing (\a -> runContT (f a) ka<&>(,a)))
    where mfixing f = fst <$> mfix (\ ~(_,a) -> f a )
newtypeconttma=ContT{runContT::forall r.(a->mr)->mr}
实例函子(ContT m),其中
fmap f(ContT k)=ContT(\kb->k(kb.f))
实例Monad(ContT m)其中
返回a=ContT($a)
join(conttkk)=ContT(\ka->kk(\(conttk)->kka))
实例MonadFix m=>MonadFix(ContT m),其中
mfix f=ContT(\ka->mfix(\a->runContT(fa)ka(,a)))
式中,mfixing f=fst mfix(\~(\~,a)->f a)

考虑延续monad的
mfix
类型签名

(a->ContT r m a)->ContT r m a
--展开新类型
(a->(a->mr)->mr)->(a->mr)->mr
这里有证据证明没有这种类型的纯粹居民

---------------------------------------------
(a->(a->mr)->mr)->(a->mr)->mr
介绍f,k
f::a->(a->mr)->mr
k::a->m r
---------------------------
m r
应用k
f::a->(a->mr)->mr
k::a->m r
---------------------------
A.
死路
f::a->(a->mr)->mr
k::a->m r
---------------------------
m r
申请f
f::a->(a->m r)->m r f::a->(a->m r)->m r
k::a->m r k::a->m r
---------------------------     ---------------------------
a->m r
死端自反性
正如您所看到的,问题在于
f
k
都希望输入类型为
a
的值。但是,没有办法变出
a
类型的值。因此,对于延续单子,
mfix
没有纯粹的居住者

请注意,您不能递归地定义
mfix
,因为
mfix f k=mfix将导致无限回归,因为没有基本情况。而且,我们不能定义
mfix fk=f
mfix f k=k?
因为即使使用递归,也无法变出
a
类型的值

但是,我们是否可以为延续monad使用不纯净的
mfix
?请考虑以下内容:

import Control.Concurrent.MVar
进口管制
导入控制.Monad.Fix
导入System.IO不安全
实例MonadFix(ContT r m)其中
mfix f=ContT$\k->unsafePerformIO$do
m ContT r m a)->ContT r m a
常数mfix=f=>k=>{
常数ys=[];
返回(函数迭代(n){
设i=0,x;
返回f(()=>{
如果(i>n)返回x;
抛出新引用错误(“未定义x”);
})(y=>{
常数j=i++;
如果(j==n){
ys[j]=k(x=y);
迭代(i);
}
返回ys[j];
});
}(0));
};
常数示例=triple=>k=>[
{a:()=>1,b:()=>2,c:()=>triple().a()+triple().b()},
{a:()=>2,b:()=>triple().c()-triple().a(),c:()=>5},
{a:()=>triple().c()-triple().b(),b:()=>5,c:()=>8},
].flatMap(k);
const result=mfix(示例)(({a,b,c})=>[{a:a(),b:b(),c:c()}]);

控制台日志(结果)看起来您的类型实际上是更受约束的类型。是否存在将参数强制为
ContT
多态会阻止有用实现的实际情况?如果不是,这可能只是一个历史问题-
ContT
已经存在很长时间了,很可能是在排名2的类型成为Haskell公认的一部分之前。多态参数
ContT
也称为
Codensity
。它缺乏定义
callCC
的能力。这个答案解释了为什么您的
用于all r。(a->m r)->m r
ContT
不能有
callCC
。好吧,我确实不能用
Codensity
(谢谢你,厄尔詹,教我一个新词:-)),来定义
Control.Monad.Cont.callCC
,但是如果我们使用一个看起来像Scheme延续的typeclass,实例几乎会自己写:
类MonadCont m where callCC:(对于所有b.(a->mb)->m b)->m a
。我们可以以一种更为一致的方式使用这个实例,即我们不直接在延拓中获取值,而是使用我们生成的值运行计算的其余部分,我们还不知道该值的类型(因此,
forall
).该证明在这种特殊情况下不具有说服力,因为它只考虑实现而不考虑递归,而递归正是
MonadFix
的关键所在。
ContT
MonadFix
实例打破了引用的透明性:
x
的值取决于是否调用延续,这取决于求值顺序,即使它最多应用一次。另一方面,如果你接受不安全,这可能是一种有趣的打结方式。@李耀霞你也不能递归地定义
mfix
,因为
mfix f k=mfix将导致无限回归,因为没有基本情况。而且,我们不能定义
mfix fk=f
mfix f k=k?
因为即使使用递归,也无法变出
a类型的值
@liyaoxia True。它确实破坏了引用的透明度。