Haskell 级联函数列表的类型是什么?

Haskell 级联函数列表的类型是什么?,haskell,types,type-systems,dependent-type,Haskell,Types,Type Systems,Dependent Type,在Haskell语法中,我们可以有一个(抽象)类型,如[a->b],它是函数a到b的列表。具体的类型是[Int->Int],例如map(*)[1..10]。是否可以有一个类似于[a->b,b->c,c->d,…]类型的级联函数列表?列表中的各个元素都是不同的(我认为),所以我认为这是不可能的。但依赖类型是否可能?它的类型签名是什么(最好是伪Haskell语法)?您不能使用普通列表,但可以按如下方式构造自己的类似列表的类型: {-# LANGUAGE GADTs #-} data Cascadi

在Haskell语法中,我们可以有一个(抽象)类型,如
[a->b]
,它是函数a到b的列表。具体的类型是
[Int->Int]
,例如
map(*)[1..10]
。是否可以有一个类似于
[a->b,b->c,c->d,…]
类型的级联函数列表?列表中的各个元素都是不同的(我认为),所以我认为这是不可能的。但依赖类型是否可能?它的类型签名是什么(最好是伪Haskell语法)?

您不能使用普通列表,但可以按如下方式构造自己的类似列表的类型:

{-# LANGUAGE GADTs #-}

data CascadingList i o where
    Id :: CascadingList i i
    Cascade :: (b -> o) -> CascadingList i b -> CascadingList i o
addOnePositive :: CascadingList Int Bool
addOnePositive = Cascade (>0) $ Cascade (+1) $ Id
然后您可以按如下方式制作这些
CascadingList
s:

{-# LANGUAGE GADTs #-}

data CascadingList i o where
    Id :: CascadingList i i
    Cascade :: (b -> o) -> CascadingList i b -> CascadingList i o
addOnePositive :: CascadingList Int Bool
addOnePositive = Cascade (>0) $ Cascade (+1) $ Id
您可以“折叠”列表:

collapse :: CascadingList a b -> a -> b
collapse Id = id
collapse (Cascade f c) = f . collapse c
那你会的

collapse addOnePositive 0 == True
注意,这并没有考虑中间函数的类型,所以它可能不是您想要的



我刚刚意识到这更接近于[c->d,b->c,a->b]。这是一个容易的改变,使它更接近你的意图;我可以编辑它,但我想你明白了。

你不能用一个简单的列表来编辑它,但是你可以像下面这样构造你自己的列表类型:

{-# LANGUAGE GADTs #-}

data CascadingList i o where
    Id :: CascadingList i i
    Cascade :: (b -> o) -> CascadingList i b -> CascadingList i o
addOnePositive :: CascadingList Int Bool
addOnePositive = Cascade (>0) $ Cascade (+1) $ Id
然后您可以按如下方式制作这些
CascadingList
s:

{-# LANGUAGE GADTs #-}

data CascadingList i o where
    Id :: CascadingList i i
    Cascade :: (b -> o) -> CascadingList i b -> CascadingList i o
addOnePositive :: CascadingList Int Bool
addOnePositive = Cascade (>0) $ Cascade (+1) $ Id
您可以“折叠”列表:

collapse :: CascadingList a b -> a -> b
collapse Id = id
collapse (Cascade f c) = f . collapse c
那你会的

collapse addOnePositive 0 == True
注意,这并没有考虑中间函数的类型,所以它可能不是您想要的



我刚刚意识到这更接近于[c->d,b->c,a->b]。这是一个容易的改变,使它更接近你的意图;我可以编辑它,但我想你明白了。

对斯堪的德格斯的回答有一点改进,解决了一些评论:

{-# LANGUAGE GADTs #-}

import Data.Typeable

data CascadingList i o where
    Id :: CascadingList i i
    Cascade :: Typeable b =>  (b -> o) -> CascadingList i b -> CascadingList i o

现在,当您在
Cascade
上进行模式匹配时,您至少可以通过使用尝试猜测
b
是哪种类型,如果猜对了,您可以实际使用内部函数。轻微的缺点是它只适用于具有
可键入的
实例的类型(GHC至少可以派生出该实例)。

对Scrambledggs的答案进行了一点改进,解决了一些问题:

{-# LANGUAGE GADTs #-}

import Data.Typeable

data CascadingList i o where
    Id :: CascadingList i i
    Cascade :: Typeable b =>  (b -> o) -> CascadingList i b -> CascadingList i o

现在,当您在
Cascade
上进行模式匹配时,您至少可以通过使用尝试猜测
b
是哪种类型,如果猜对了,您可以实际使用内部函数。轻微的缺点是,它只适用于具有
可键入
实例(GHC至少可以派生)的类型。

使用
数据类型
,可以公开集合的内部类型,这可能会使使用组成部分变得更容易:

{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
module Cascade where
import Control.Monad ((>=>), liftM)
import Control.Category ((>>>))

data Cascade (cs :: [*]) where
  End :: Cascade '[a]
  (:>>>) :: (a -> b) -> Cascade (b ': cs) -> Cascade (a ': b ': cs)
infixr 5 :>>>

-- a small example
fs :: Cascade '[ String, Int, Float ]
fs = read :>>> fromIntegral :>>> End

-- alternate using functions from one chain then the other
zigzag :: Cascade as -> Cascade as -> Cascade as
zigzag End End = End
zigzag (f :>>> fs) (_ :>>> gs) = f :>>> zigzag gs fs

-- compose a chain into a single function
compose :: Cascade (a ': as) -> a -> Last (a ': as)
compose End = id
compose (f :>>> fs) = f >>> compose fs

-- generalizing Either to a union of multiple types
data OneOf (cs :: [*]) where
  Here :: a -> OneOf (a ': as)
  There :: OneOf as -> OneOf (a ': as)

-- start the cascade at any of its entry points
fromOneOf :: Cascade cs -> OneOf cs -> Last cs
fromOneOf fs (Here a) = compose fs a
fromOneOf (_ :>>> fs) (There o) = fromOneOf fs o

-- generalizing (,) to a product of multiple types
data AllOf (cs :: [*]) where
  None :: AllOf '[]
  (:&) :: a -> AllOf as -> AllOf (a ': as)
infixr 5 :&

-- end the cascade at all of its exit points
toAllOf :: Cascade (a ': as) -> a -> AllOf (a ': as)
toAllOf End a        = a :& None
toAllOf (f :>>> fs)  a = a :& toAllOf fs (f a)

-- start anywhere, and end everywhere after that
fromOneOfToAllOf :: Cascade cs -> OneOf cs -> OneOf (Map AllOf (Tails cs))
fromOneOfToAllOf fs (Here a) = Here $ toAllOf fs a
fromOneOfToAllOf (_ :>>> fs) (There o) = There $ fromOneOfToAllOf fs o

-- type level list functions
type family Map (f :: a -> b) (as :: [a]) where
  Map f '[] = '[]
  Map f (a ': as) = f a ': Map f as

type family Last (as :: [*]) where
  Last '[a] = a
  Last (a ': as) = Last as

type family Tails (as :: [a]) where
  Tails '[] = '[ '[] ]
  Tails (a ': as) = (a ': as) ': Tails as

-- and you can do Monads too!
data CascadeM (m :: * -> *) (cs :: [*]) where
  EndM :: CascadeM m '[a]
  (:>=>) :: (a -> m b) -> CascadeM m (b ': cs) -> CascadeM m (a ': b ': cs)
infixr 5 :>=>

composeM :: Monad m => CascadeM m (a ': as) -> a -> m (Last (a ': as))
composeM EndM = return
composeM (f :>=> fs) = f >=> composeM fs

fromOneOfM :: Monad m => CascadeM m cs -> OneOf cs -> m (Last cs)
fromOneOfM fs (Here a) = composeM fs a
fromOneOfM (_ :>=> fs) (There o) = fromOneOfM fs o

-- end the cascade at all of its exit points
toAllOfM :: Monad m => CascadeM m (a ': as) -> a -> m (AllOf (a ': as))
toAllOfM EndM a        = return $ a :& None
toAllOfM (f :>=> fs)  a = do
  as <- toAllOfM fs =<< f a
  return $ a :& as

-- start anywhere, and end everywhere after that
fromOneOfToAllOfM :: Monad m => CascadeM m cs -> OneOf cs -> m (OneOf (Map AllOf (Tails cs)))
fromOneOfToAllOfM fs (Here a) = Here `liftM` toAllOfM fs a
fromOneOfToAllOfM (_ :>=> fs) (There o) = There `liftM` fromOneOfToAllOfM fs o
{-#语言多样性}
{-#语言类型族{-}
{-#语言签名{-}
{-#语言类型运算符{-}
{-#语言数据类型}
{-#语言GADTs}
模块级联在哪里
导入控制.Monad((>=>),liftM)
进口管制.类别(>>>))
数据级联(cs::[*]),其中
结束::级联'[a]
(:>>>):::(a->b)->级联(b):cs)->级联(a):b:cs)
infixr 5:>>>
--一个小例子
fs::Cascade'[String,Int,Float]
fs=读取:>>>从积分:>>>结束
--交替使用一个链中的函数,然后使用另一个链中的函数
锯齿形::级联为->级联为->级联为
锯齿形末端=末端
锯齿形(f:>>>>fs)(:>>>gs)=f:>>>>锯齿形gs-fs
--将链组成单个函数
组合::级联(a):as)->a->Last(a):as
组合结束=id
组合(f:>>>fs)=f>>>组合fs
--将其中一个泛化为多个类型的并集
(cs::[*])中的数据,其中
Here::a->OneOf(a):as
There::OneOf as->OneOf(a):as
--在级联的任何入口点启动级联
fromOneOf::Cascade cs->OneOf cs->Last cs
fromOneOf fs(此处a)=合成fs a
fromOneOf(:>>>fs)(There o)=fromOneOf fs o
--将(,)推广到多种类型的产品
所有数据(cs::[*]),其中
None::AllOf'[]
(:&)::a->AllOf as->AllOf(a):as)
infixr 5:&
--在级联的所有出口点结束级联
toAllOf::Cascade(a):as)->a->AllOf(a):as
toAllOf End a=a:&无
toAllOf(f:>>>fs)a=a:&toAllOf fs(f a)
--从任何地方开始,然后到处结束
fromOneOfToAllOf::级联cs->OneOfCS->OneOf(映射所有(尾部cs))
FromOne of toAllOf fs(此处a)=此处$toAllOf fs a
fromOneOfToAllOf(:>>fs)(There o)=There$fromOneOfToAllOf fs o
--类型级别列表函数
键入族映射(f::a->b)(as::[a]),其中
映射f'[]='[]
映射f(a):as)=fa”:映射f:as
键入family Last(作为::[*]),其中
最后的'[a]=a
Last(a):as)=Last as
键入族尾(as::[a]),其中
尾部'[]='['[]]
尾部(a):as)=(a):as':尾部为
--你也可以做单子!
数据级联m(m::*->*)(cs::[*]),其中
EndM::级联m'[a]
(:>=>)::(a->mb)->cascademm(b):cs)->cascademm(a):b:cs)
infixr 5:>=>
composeM::Monad m=>CascadeM m(a':as)->a->m(Last(a':as))
composeM EndM=返回
复合结构(f:>=>fs)=f>=>
fromOneOfM::Monad m=>cascademcs->oneofcs->m(最后一个cs)
fromOneOfM fs(此处为a)=复合fs a
fromOneOfM(:>=>fs)(There o)=fromOneOfM fs o
--在级联的所有出口点结束级联
toAllOfM::Monad m=>CascadeM(a':as)->a->m(AllOf(a':as))
toAllOfM EndM a=返回$a:&无
toAllOfM(f:>=>fs)a=do
作为一个cs->m(一个(映射所有(尾部cs)))
from one of toAllOfM fs(此处a)=此处'liftM'至allofm fs a
fromooneoftoallofm(:>=>fs)(There o)=There`liftM`fromooneoftoallofm fs o

使用
数据种类
,您可以公开集合的内部类型,这可能会使使用组成部分变得更容易:

{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
module Cascade where
import Control.Monad ((>=>), liftM)
import Control.Category ((>>>))

data Cascade (cs :: [*]) where
  End :: Cascade '[a]
  (:>>>) :: (a -> b) -> Cascade (b ': cs) -> Cascade (a ': b ': cs)
infixr 5 :>>>

-- a small example
fs :: Cascade '[ String, Int, Float ]
fs = read :>>> fromIntegral :>>> End

-- alternate using functions from one chain then the other
zigzag :: Cascade as -> Cascade as -> Cascade as
zigzag End End = End
zigzag (f :>>> fs) (_ :>>> gs) = f :>>> zigzag gs fs

-- compose a chain into a single function
compose :: Cascade (a ': as) -> a -> Last (a ': as)
compose End = id
compose (f :>>> fs) = f >>> compose fs

-- generalizing Either to a union of multiple types
data OneOf (cs :: [*]) where
  Here :: a -> OneOf (a ': as)
  There :: OneOf as -> OneOf (a ': as)

-- start the cascade at any of its entry points
fromOneOf :: Cascade cs -> OneOf cs -> Last cs
fromOneOf fs (Here a) = compose fs a
fromOneOf (_ :>>> fs) (There o) = fromOneOf fs o

-- generalizing (,) to a product of multiple types
data AllOf (cs :: [*]) where
  None :: AllOf '[]
  (:&) :: a -> AllOf as -> AllOf (a ': as)
infixr 5 :&

-- end the cascade at all of its exit points
toAllOf :: Cascade (a ': as) -> a -> AllOf (a ': as)
toAllOf End a        = a :& None
toAllOf (f :>>> fs)  a = a :& toAllOf fs (f a)

-- start anywhere, and end everywhere after that
fromOneOfToAllOf :: Cascade cs -> OneOf cs -> OneOf (Map AllOf (Tails cs))
fromOneOfToAllOf fs (Here a) = Here $ toAllOf fs a
fromOneOfToAllOf (_ :>>> fs) (There o) = There $ fromOneOfToAllOf fs o

-- type level list functions
type family Map (f :: a -> b) (as :: [a]) where
  Map f '[] = '[]
  Map f (a ': as) = f a ': Map f as

type family Last (as :: [*]) where
  Last '[a] = a
  Last (a ': as) = Last as

type family Tails (as :: [a]) where
  Tails '[] = '[ '[] ]
  Tails (a ': as) = (a ': as) ': Tails as

-- and you can do Monads too!
data CascadeM (m :: * -> *) (cs :: [*]) where
  EndM :: CascadeM m '[a]
  (:>=>) :: (a -> m b) -> CascadeM m (b ': cs) -> CascadeM m (a ': b ': cs)
infixr 5 :>=>

composeM :: Monad m => CascadeM m (a ': as) -> a -> m (Last (a ': as))
composeM EndM = return
composeM (f :>=> fs) = f >=> composeM fs

fromOneOfM :: Monad m => CascadeM m cs -> OneOf cs -> m (Last cs)
fromOneOfM fs (Here a) = composeM fs a
fromOneOfM (_ :>=> fs) (There o) = fromOneOfM fs o

-- end the cascade at all of its exit points
toAllOfM :: Monad m => CascadeM m (a ': as) -> a -> m (AllOf (a ': as))
toAllOfM EndM a        = return $ a :& None
toAllOfM (f :>=> fs)  a = do
  as <- toAllOfM fs =<< f a
  return $ a :& as

-- start anywhere, and end everywhere after that
fromOneOfToAllOfM :: Monad m => CascadeM m cs -> OneOf cs -> m (OneOf (Map AllOf (Tails cs)))
fromOneOfToAllOfM fs (Here a) = Here `liftM` toAllOfM fs a
fromOneOfToAllOfM (_ :>=> fs) (There o) = There `liftM` fromOneOfToAllOfM fs o
{-#语言多样性}
{-#语言类型族{-}
{-#语言签名{-}
{-#语言类型运算符{-}
{-#语言数据类型}
{-#语言GADTs}
模块级联在哪里
导入控制.Monad((>=>),liftM)
进口管制.类别((