【问题标题】:What’s going on with these Haskell types?这些 Haskell 类型是怎么回事?
【发布时间】: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

【问题讨论】:

    标签: haskell types


    【解决方案1】:

    length 具有Foldable t =&gt; t a -&gt; Int 类型,这意味着length xs 是一个Int 值。这使得[1..(length xs)] 的类型为[Int] 等。

    另一方面,

    100 不是 Int 文字,而是Num a =&gt; a 类型的多态文字。这使得[1..100] 具有Num a =&gt; [a] 等类型。

    也就是说,length 是唯一在最终类型中强制使用像 Int 这样的具体类型的东西。将其替换为更通用的100,最终类型也更通用。

    【讨论】:

    • 所以,如果我理解的话,这归结为 (length [1,2,3]) * 4.5 在 Haskell 中是不可能的?
    • 谢谢! fromIntegral 看起来很有用。
    • (*) 的类型为 Num a =&gt; a -&gt; a -&gt; a。两个操作数必须具有相同的类型,所以不,length [1,2,3] * 4.5 不进行类型检查。
    • "两个操作数必须具有相同的类型" 好的,这就是我必须学习的重点。
    • 请注意Data.List 提供genericLength :: Num i =&gt; [a] -&gt; i,它使用您请求的任何Num 实例来提供长度。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-06
    • 2011-06-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多