在Haskell语法中,我们可以有一个(抽象)类型,如[a -> b]
,它是函数a到b的列表。具体的类型是[Int -> Int]
,比如map (*) [1..10]
。是否有可能有一个类似[a -> b, b -> c, c -> d, ...]
类型的级联函数列表?列表中的各个元素都是不同的(我认为),所以我不认为这是可能的。但是依赖类型可能吗?它的类型签名是什么(最好是伪哈斯克尔语法)?级联函数列表的类型是什么?
回答
你不能做到这一点与普通的名单,但你可以构建自己的列表类似的类型,如下所示:
{-# LANGUAGE GADTs #-}
data CascadingList i o where
Id :: CascadingList i i
Cascade :: (b -> o) -> CascadingList i b -> CascadingList i o
然后可以按如下方式使这些CascadingList
S:
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]更接近。让它更接近你的意图是一个容易的改变;我可以编辑它,但我认为你明白了。
正如我在[回答上一个问题](http://stackoverflow.com/a/26566362/1186208)中指出的那样,后续问题(和观察)是:这样的集合是什么让你超过函数组成? (具有不同“类别”的相同构造可能是另一回事......) – 2014-10-27 18:12:57
我可以看到的一个潜在优势是可以从这种结构中提取组合函数,但对于简单的函数组合而言并非如此。一个人为的例子:“(+1)。 (-1)==(-1)。 (+1)'',但'[(+1),( - 1)]/= [(-1),(+ 1)]''(显然滥用符号)。 – 2014-10-27 19:03:34
是的,我也注意到了。但你不能对他们做很多事情;除其他外,你无法从GADT之外预测它们的类型。 – 2014-10-27 19:06:40
上scrambledeggs'回答一个小小的改进,解决一些评论:
{-# 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
是利用the eqT
and cast
functions from Data.Typeable
,如果你猜对了,你实际上可以使用里面的函数。轻微的缺点是它只适用于具有Typeable
实例(GHC至少可以导出)的类型。
使用DataKinds
,可以公开的内部集合类型,这可能使使用组成部分容易的:
{-# 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
我认为'Chain'也可以被实现为(封闭)类型的类型,因为类型参数'cs'明确指出将使用哪些构造函数。 – 2014-10-27 20:55:28
Christian Conkle:是的,我做了这个[OneOf'](http://stackoverflow.com/questions/25414521/types-for-parser-combinators)。我现在在瞎搞。 – rampion 2014-10-27 20:59:15
Christian Conkle:现在我放弃了封闭型家庭,因为当我试图做任何有趣的事情时,我总是感到内射型错误。 – rampion 2014-10-28 01:19:39
- 1. 什么是类型和什么是类型构造函数scala
- 2. 什么是函数的类型提示
- 3. `main0`函数的类型是什么?
- 4. 什么是lambda函数的类型?
- 5. 级联样式表中“级联”的含义是什么?
- 6. 什么是内联函数?
- 7. 什么类型是构造函数?
- 8. 什么是参数的类型,这个函数做什么?
- 9. 什么是顶级类型和嵌套级别类型?
- 10. 下拉列表是什么类型?
- 11. 什么是“级联规则”?
- 12. 什么是X-级联集
- 13. 函数有什么类型?
- 14. 类型级列表
- 15. 什么是函数赋值函数类型的flex(ActionScript3)语法?
- 16. Hibernate级联类型还是别的?
- 17. 什么是列表的顶级?
- 18. 什么是列数据类型Sharepoint列数据类型中的业务数据?
- 19. 什么是存储multiselect选取列表的数据类型?
- 20. Scala中可变长度参数列表的类型是什么?
- 21. 如何编写类型级别列表的交集函数
- 22. 递归函数类型错误:只能串联列表(不是“浮动”),列出
- 23. Riak二级索引数据类型的目的是什么?
- 24. 什么是散列函数?
- 25. 多级分类的成本函数是什么?
- 26. 这是什么类型的声明?一个函数?类?
- 27. 成功数据的类型是什么:函数(数据)?
- 28. 蟒蛇是什么级别的数据类型= {S}
- 29. C++类型的函数参数的含义是什么?
- 30. 多级分类列表/树PHP函数
你不能做到这一点与在Haskell平原名单,但它是可能的。查看HList库以获取异构列表。要警告的是,该库有很多扩展来获得这种动态行为。 – bheklilr 2014-10-27 17:27:53
看看http://stackoverflow.com/questions/26565306/how-to-define-a-multiple-composition-function .... – jamshidh 2014-10-27 17:34:08
这是一个(问题jamshidh链接的一个子集)的重复。然而,这个问题更直接地说明了这个问题。 – 2014-10-27 18:07:23