这些 Haskell 类型是怎么回事?
Posted
技术标签:
【中文标题】这些 Haskell 类型是怎么回事?【英文标题】:What’s going on with these Haskell types? 【发布时间】:2022-01-23 02:50:45 【问题描述】:为什么这个函数需要一个整数列表?
Prelude> :t \xs->[(map $ uncurry(*)) (zip xs [1..n]) | n<-[1..(length xs)]]
\xs->[(map $ uncurry(*)) (zip xs [1..n]) | n<-[1..(length xs)]]
:: [Int] -> [[Int]]
当我将length xs
替换为固定值时,类型会发生变化并且不再那么严格:
Prelude> :t \xs->[(map $ uncurry(*)) (zip xs [1..n]) | n<-[1..100]]
\xs->[(map $ uncurry(*)) (zip xs [1..n]) | n<-[1..100]]
:: (Num b, Enum b) => [b] -> [[b]]
我的编译器是
$ ghci --version
The Glorious Glasgow Haskell Compilation System, version 8.8.4
【问题讨论】:
【参考方案1】:length
具有Foldable t => t a -> Int
类型,这意味着length xs
是一个Int
值。这使得[1..(length xs)]
的类型为[Int]
等。
100
不是 Int
文字,而是Num a => a
类型的多态文字。这使得[1..100]
具有Num a => [a]
等类型。
也就是说,length
是唯一在最终类型中强制使用像 Int
这样的具体类型的东西。将其替换为更通用的100
,最终类型也更通用。
【讨论】:
所以,如果我理解的话,这归结为(length [1,2,3]) * 4.5
在 Haskell 中是不可能的?
谢谢! fromIntegral
看起来很有用。
(*)
的类型为 Num a => a -> a -> a
。两个操作数必须具有相同的类型,所以不,length [1,2,3] * 4.5
不进行类型检查。
"两个操作数必须具有相同的类型" 好的,这就是我必须学习的重点。
请注意Data.List
提供genericLength :: Num i => [a] -> i
,它使用您请求的任何Num
实例来提供长度。以上是关于这些 Haskell 类型是怎么回事?的主要内容,如果未能解决你的问题,请参考以下文章
Rust闭包和Haskell lambda有什么区别? [关闭]