为什么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
。