我发现了这些类型的签名:
x :: a b -> Int
x f = 3
y :: a b c -> Int
y f = 3
z :: a b c d -> Int
z f = 3
> x [1] -- 3
> y (1, 2) -- 3
> z (1, 2, 3) -- 3
基本上:
它们是有效的,但我不确定它们的含义以及它们可用于什么。
它们似乎与类型构造函数上的多型概念或多态相关,但是基于类型构造函数接受的许多参数强制执行不变量。
答案 0 :(得分:8)
没有进一步的限制,这些类型是无用的 - 你无法用它们做任何事情,期望它们正确传递。但实际情况与签名a -> Int
的情况相同:如果对a
一无所知,那么你也无能为力!
然而,与例如toInteger :: Integral a => a -> Integer
,为参数添加约束可以让你做一些事情。例如,
import Data.Foldable
import Prelude hiding (foldr)
x' :: (Foldable a, Integral b) => a b -> Integer
x' = foldr ((+) . toInteger) 0
通常情况下,如果您的表单类型为a b ... n o p q
,那么a b ... p
至少是Functor
类的一个实例,通常也是Applicative
和Monad
;有时候Foldable
,Traversable
或Comonad
;有时a b ... o
将是Arrow
...这些约束允许您对复合类型做很多事情,而不知道您正在处理哪些特定类型构造函数。
答案 1 :(得分:0)
在研究了@leftaroundabout回答并在GHCI中进行实验后,我已经了解了复合类型。它们与应用类型的统一基于评估顺序和它们的类型变量的类型签名。评估顺序非常重要,a b c ~ (((a) b) c)
a (b c)
为(a ((b) c)
。这使得a b c
匹配复合类型,其中a
与类* -> * -> *
的类型构造函数匹配,a b
与* -> *
和a b c
与{{{ 1}}。
我在这个要点(https://gist.github.com/CMCDragonkai/2a1d3ecb67dcdabfc7e0)中用图表和GHCI代码完全解释了它(它对于堆栈溢出而言太长了)