为什么haskell总是强制键入泛型类型?

为什么haskell总是强制键入泛型类型?,haskell,types,Haskell,Types,假设我们有: data Data a b c = Build (a,b,c) deriving Show foo :: Data a b c -> Data a b c foo d = d main = print $ foo $ Build (1, 1, "a") 是否有任何方法可以避免每次使用数据类型时写入abc 使用类型,例如: foo :: Data -> Data foo d = d 是的,当然可以: foo :: d ~ Data a b c => d -&

假设我们有:

data Data a b c = Build (a,b,c) deriving Show

foo :: Data a b c -> Data a b c
foo d = d

main = print $ foo $ Build (1, 1, "a")
是否有任何方法可以避免每次使用数据类型时写入
abc

使用类型,例如:

foo :: Data -> Data
foo d = d
是的,当然可以:

foo :: d ~ Data a b c => d -> d

因为
Data
不是一个类型,而是一个类型构造函数。如果您更喜欢接受3种类型并返回新类型的函数。类型构造函数也可以将其他类型构造函数作为参数示例

  data D d a= D (d a a a)
然后我可以使用您的
数据
(无参数)
D数据a

data Data a b c = Build (a,b,c) deriving Show
type D a t a' = Data a t a'

foo :: D a t a' -> D a t a'
foo d = d
别名很有趣,但这并不是一个严肃的答案

编辑:一个严肃的版本,如果您知道一种常见的单态类型,那么别名将变得有用:

type AppData = Data AppState AppValue AppResult
foo :: AppData -> AppData
...

您可以将多态类型包装为
类型
同义词

{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeOperators #-}

type d ~> d' = forall a b c. d a b c -> d' a b c

foo :: Data ~> Data
foo d = d

不过,只写类型变量可能更简单。

实际上,您根本不必写类型签名。如果你省略了它们,哈斯凯尔会为你导出它们。@WillemVanOnsem,我知道这一点,假设除此之外。威尔:回答得很好。很有创意,干得好@DanielSanchez不,那是一个问题。基本上,它说类型
d
必须等于
dataabc
,但是可以有更复杂的约束,比如
aabc~bdef
。Haskell确实有类型同义词,但您要么将它们设为2级,要么添加参数。@DanielSanchez我认为您不应该使用这些建议中的任何一个。我认为你应该写出类型变量。DanielWagner是专家(不客气);作为Haskell的学习者,我认为你应该首先学习如何使用它的编程模型。这意味着转向远离诸如类型相等之类的高级功能。我不完全理解这一点,你能从web链接或其他什么给我一些提示吗?thanks@DanielSanchez:简而言之,当签名中有类型变量时,它们隐式地有定义其作用域的量词,因此
foo::Data a b c->Data a b c
隐式地
用于所有a b c。数据a b c->数据a b c
。类型
Data~>Data
扩展为相同的内容,
forall a b c。通过将
d
d'
替换为
Data
,数据AB c->Data AB c