Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/flash/4.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 递归型族_Haskell_Type Families - Fatal编程技术网

Haskell 递归型族

Haskell 递归型族,haskell,type-families,Haskell,Type Families,我正在试验一个mtl风格的类,它允许我将Pipe组合提升到外部monad上。为此,我必须定义该类型的哪两个变量是Pipecomposition的domain和codomain 我尝试使用关联的类型族方法,但无效: {-# LANGUAGE TypeFamilies #-} import Control.Monad.Trans.Free import Control.Monad.Trans.State import Control.Pipe hiding (Pipe) data Pipe a

我正在试验一个
mtl
风格的类,它允许我将
Pipe
组合提升到外部monad上。为此,我必须定义该类型的哪两个变量是
Pipe
composition的domain和codomain

我尝试使用关联的类型族方法,但无效:

{-# LANGUAGE TypeFamilies #-}

import Control.Monad.Trans.Free
import Control.Monad.Trans.State
import Control.Pipe hiding (Pipe)

data Pipe a b m r = Pipe { unPipe :: FreeT (PipeF a b) m r }

class MonadPipe m where
    type C a b (m :: * -> *) :: * -> *
    idT :: C a a m r
    (<-<) :: C b c m r -> C a b m r -> C a c m r

instance (Monad m) => MonadPipe (Pipe i o m) where
    type C a b (Pipe i o m) = Pipe a b m
    idT = Pipe idP
    (Pipe p1) <-< (Pipe p2) = Pipe (p1 <+< p2)

instance (MonadPipe m) => MonadPipe (StateT s m) where
    type C a b (StateT s m) = StateT s (C a b m)
    idT = StateT $ \s -> idT
    (StateT f1) <-< (StateT f2) = StateT $ \s -> f1 s <-< f2 s
{-#语言类型族}
进口管制。单体。无反式
进口管制.单子.跨州
导入控制。管道隐藏(管道)
数据管道a b m r=管道{unPipe::FreeT(PipeF a b)m r}
MonadPipe m类,其中
类型C a b(m::*->*)::*->*
idT::C a m r
(C a C m r)
实例(Monad m)=>MonadPipe(Pipe i o m),其中
类型C a b(管道i o m)=管道a b m
idT=管道idP
(管道p1)idT
(StateT f1)f1 s idT
在“MonadPipe(StateT s m)”的实例声明中
家庭。hs:24:10:
无法推断(cbcm~cb0 c0 m1)
从上下文(MonadPipe m)
受family的实例声明约束。hs:21:14-52
注意:`C'是一个类型函数,可能不是内射函数
预期类型:C b C(StateT s m)r
实际类型:状态s(C b0 c0 m1)r
在模式中:StateT f1

在`的等式中,类型推断在默认情况下是一个猜测游戏。Haskell的表面语法使得明确哪些类型应该为所有
实例化变得相当尴尬,即使你知道你想要什么。这是Damas Milner完备性的好时代遗留下来的,当时的想法非常有趣,需要明确的解释平只是被禁止了

让我们想象一下,我们可以使用Agda样式的
f{a=x}
符号,在模式和表达式中显式地创建类型应用程序,有选择地访问
f
的类型签名中与
a
对应的类型参数

idT = StateT $ \ s -> idT
应该是指

idT {a = a}{m = m} = StateT $ \ s -> idT {a = a}{m = m}
因此,左边有类型
caa(StateT s m)r
,右边有类型
StateT s(cam)r
,根据类型族的定义,它们是相等的,欢乐辐射全球。但这不是你所写的含义。“变量规则”为了调用多态性,需要用一个新的存在类型变量实例化每个
forall
,然后通过统一来解决

idT {a = a}{m = m} = StateT $ \ s -> idT {a = a'}{m = m'}
  -- for a suitably chosen a', m'
计算类型族后,可用约束为

C a a m ~ C a' a' m'
但这并没有简化,也不应该简化,因为没有理由假设
C
是内射的。令人恼火的是,机器比你更关心找到最普遍解决方案的可能性。你已经想到了一个合适的解决方案,但问题是在默认假设为n是猜测

有许多策略可以帮助您摆脱这种困境。其中一种是使用数据族。赞成:注入能力没问题。反对:构造函数。(警告,下面是未经测试的推测。)

然后在操作类型中使用
WrapC
,使typechecker保持在正确的轨道上。我不知道这是否是一个好策略,但我计划有一天找出答案

一个更直接的策略是使用代理、幻象类型和作用域类型变量(尽管本例不需要它们)

这只是使类型应用程序显式化的一种拙劣方法。请注意,有些人使用
a
本身而不是
Proxy a
,并将
undefined
作为参数传递,因此无法在类型中标记代理,并且依赖于不会意外地对其进行评估。
PolyKinds
的最新进展可能在east的意思是我们只能有一种多态幻影代理类型。关键是,
代理
类型构造函数是内射的,所以我的代码实际上是说“这里和那里的参数相同”


但是,有时我希望我可以在源代码中降低到系统FC级别,或者以其他方式表达一个明确的手动重写来进行类型推断。在依赖类型的社区中,这样的事情是相当标准的,在那里没有人想象机器可以在没有任何提示的情况下解决所有问题,或者隐藏参数的情况下解决所有问题没有值得检查的信息。函数的隐藏参数可以在使用场所被抑制,但需要在定义中明确,这是很常见的。Haskell的现状基于一种文化假设,即“类型推断就足够了”它已经脱离轨道一代人了,但仍然以某种方式存在。

编辑了三次:数据族版本见底部。并将GADT版本更改为drop m

让我猜猜:剩菜

让我先来看看类型错误,这是一个解决方案

The class defines :
type C a0 b0 m  where a0 and b0 are fresh.
idT :: C a a m r, where a and r are fresh. 

The idT in the (Pipe i o m0) instance is okay by what I think is the logic:
LHS is idT :: C a0 a0 (Pipe i o m0) r0 which becomes Pipe a0 a0 m0 r0
RHS is Pipe idP :: Pipe a1 a1 m1 r1 starts fresh
And then these unify
because Pipe is a data constructor.

The idT in the MonadPipe m0 => (StateT s0 m0) instance:
LHS is idT :: C a0 a0 (StateT s0 m0) which becomes StateT s0 (C a0 a0 m0)
RHS is StateT (\s -> idT) :: StateT s1 m1 r1
Some unification seems to happen...
RHS is StateT (\s -> idT) :: StateT s1 (C a0 a0 m0) r1
  where expression idT :: MonadPipe m1 => (C a2 a2 m2) r2 starts fresh
        context of idT :: (C a0 a0 m0) (a1, s1)
And then (C a0 a0 m0) does not unify with (C a1 a2 m2)
because C is a type constructor.
如果类型族成为数据族,则您以前的
newtype
创建类别实例的方法可能在这里起作用

编辑:您可以更改参数的顺序并键入StateT来解决该问题:

{-# LANGUAGE TypeFamilies, MultiParamTypeClasses #-}

import Control.Monad.Trans.Free
import Control.Monad.Trans.State
import Control.Pipe hiding (Pipe)

data Pipe m a b r = Pipe { unPipe :: FreeT (PipeF a b) m r }

newtype StatePipe s mp a b r = SP (StateT s (mp a b) r)

class MonadPipe mp where
    idT :: mp a a r
    (<-<) :: mp b c r -> mp a b r -> mp a c r

instance (Monad m) => MonadPipe (Pipe m) where
    idT = Pipe idP
    (Pipe p1) <-< (Pipe p2) = Pipe (p1 <+< p2)

instance (MonadPipe mp) => MonadPipe (StatePipe s mp) where
     idT = SP . StateT $ \s -> idT
     (SP (StateT f1)) <-< (SP (StateT f2)) = SP . StateT $ \s -> f1 s <-< f2 s
{-#语言类型族,多语言类型类#-}
进口管制。单体。无反式
进口管制.单子.跨州
导入控制。管道隐藏(管道)
数据管道m a b r=管道{unPipe::FreeT(PipeF a b)m r}
新类型StatePipe s mp a b r=SP(StateT s(mp a b)r)
类MonadPipe mp,其中
idT::mp a r
(mp a c r)
实例(Monad m)=>MonadPipe(管道m),其中
idT=管道idP
(管道p1)idT
(SP(StateT f1))f1 s管道()a b m r
LPipe::StateT s1(管道s2 a b m)r->Pipe(s1,s2)a b m r
类MonadPipe s在哪里
idT::Monad m=>管道s a m r
(管道s a b m r->管道s a c m r
实例MonadPipe(),其中
idT=管道idP
(管道p1)idT)
(LPipe(StateT f1))(f1 s1*->(*->*)->*->->->*
newtype实例GPipe()abmr=Pipe{unPipe::FreeT(pipefab)mr}
新类型实例GPipe(s1,s2)abmr=LPipe(statets1(gpipes2abm)r)
类MonadPipe s在哪里
idT::Monad m=>GPipe s a m r
(G管道s a b m r->G
newtype WrapC a b m r = WrapC {unwrapC :: C a b m r}
data Proxy (a :: *) = Poxy
data ProxyF (a :: * -> *) = PoxyF

class MonadPipe m where
  data C a b (m :: * -> *) r
  idT :: (Proxy a, ProxyF m) -> C a a m r
  ...

instance (MonadPipe m) => MonadPipe (StateT s m) where
  data C a b (StateT s m) r = StateTPipe (StateT s (C a b m) r)
  idT pp = StateTPipe . StateT $ \ s -> idT pp
The class defines :
type C a0 b0 m  where a0 and b0 are fresh.
idT :: C a a m r, where a and r are fresh. 

The idT in the (Pipe i o m0) instance is okay by what I think is the logic:
LHS is idT :: C a0 a0 (Pipe i o m0) r0 which becomes Pipe a0 a0 m0 r0
RHS is Pipe idP :: Pipe a1 a1 m1 r1 starts fresh
And then these unify
because Pipe is a data constructor.

The idT in the MonadPipe m0 => (StateT s0 m0) instance:
LHS is idT :: C a0 a0 (StateT s0 m0) which becomes StateT s0 (C a0 a0 m0)
RHS is StateT (\s -> idT) :: StateT s1 m1 r1
Some unification seems to happen...
RHS is StateT (\s -> idT) :: StateT s1 (C a0 a0 m0) r1
  where expression idT :: MonadPipe m1 => (C a2 a2 m2) r2 starts fresh
        context of idT :: (C a0 a0 m0) (a1, s1)
And then (C a0 a0 m0) does not unify with (C a1 a2 m2)
because C is a type constructor.
{-# LANGUAGE TypeFamilies, MultiParamTypeClasses #-}

import Control.Monad.Trans.Free
import Control.Monad.Trans.State
import Control.Pipe hiding (Pipe)

data Pipe m a b r = Pipe { unPipe :: FreeT (PipeF a b) m r }

newtype StatePipe s mp a b r = SP (StateT s (mp a b) r)

class MonadPipe mp where
    idT :: mp a a r
    (<-<) :: mp b c r -> mp a b r -> mp a c r

instance (Monad m) => MonadPipe (Pipe m) where
    idT = Pipe idP
    (Pipe p1) <-< (Pipe p2) = Pipe (p1 <+< p2)

instance (MonadPipe mp) => MonadPipe (StatePipe s mp) where
     idT = SP . StateT $ \s -> idT
     (SP (StateT f1)) <-< (SP (StateT f2)) = SP . StateT $ \s -> f1 s <-< f2 s
{-# LANGUAGE MultiParamTypeClasses, GADTs, FlexibleInstances #-}
import Control.Monad.Trans.Free
import Control.Monad.Trans.State
import Control.Pipe hiding (Pipe)

data Pipe s a b m r where
  FPipe :: { unPipe :: FreeT (PipeF a b) m r } -> Pipe () a b m r
  LPipe :: StateT s1 (Pipe s2 a b m) r -> Pipe (s1,s2) a b m r

class MonadPipe s where
    idT :: Monad m => Pipe s a a m r
    (<-<) :: Monad m => Pipe s b c m r -> Pipe s a b m r -> Pipe s a c m r

instance MonadPipe () where
    idT  = FPipe idP
    (FPipe p1) <-< (FPipe p2) = FPipe (p1 <+< p2)

instance MonadPipe s2 => MonadPipe (s1,s2) where
    idT  = LPipe (StateT $ \s -> idT)
    (LPipe (StateT f1)) <-< (LPipe (StateT f2)) = 
       LPipe (StateT $ \s1 -> (f1 s1 <-< f2 s1))
{-# LANGUAGE TypeFamilies #-}
import Control.Monad.Trans.Free
import Control.Monad.Trans.State
import Control.Pipe hiding (Pipe)

data family GPipe s :: * -> * -> (* -> *) -> * -> *
newtype instance GPipe () a b m r = Pipe { unPipe :: FreeT (PipeF a b) m r }
newtype instance GPipe (s1,s2) a b m r = LPipe ( StateT s1 (GPipe s2 a b m) r )

class MonadPipe s where
  idT :: Monad m => GPipe s a a m r
  (<-<) :: Monad m => GPipe s b c m r -> GPipe s a b m r -> GPipe s a c m r

instance MonadPipe () where
  idT = Pipe idP
  (Pipe p1) <-< (Pipe p2) = Pipe (p1 <+< p2)

instance MonadPipe s2 => MonadPipe (s1,s2) where
  idT = LPipe (StateT (\s -> idT))
  (LPipe (StateT f1)) <-< (LPipe (StateT f2)) = LPipe (StateT (\s -> f1 s <-< f2 s))