Haskell 在'中键入声明;其中';——什么';发生什么事了?

Haskell 在'中键入声明;其中';——什么';发生什么事了?,haskell,types,where-clause,Haskell,Types,Where Clause,在阅读时,我遇到了以下示例: prop_RevRev xs = reverse (reverse xs) == xs where types = xs::[Int] 手册接着说: 属性必须具有单态类型`多态性属性(如上面的属性)必须限制为用于测试的特定类型。这样做很方便,可以在 其中类型=(x1::t1,x2::t2,…) 条款。请注意,类型不是一个关键字;这只是一个本地声明,它提供了一个方便的地方来限制x1、x2等的类型 我以前在哈斯克尔从没见过这样的把戏。以下是我真正遇到的问题: 为什

在阅读时,我遇到了以下示例:

prop_RevRev xs = reverse (reverse xs) == xs
  where types = xs::[Int]
手册接着说:

属性必须具有单态类型`多态性属性(如上面的属性)必须限制为用于测试的特定类型。这样做很方便,可以在

其中类型=(x1::t1,x2::t2,…)

条款。请注意,类型不是一个关键字;这只是一个本地声明,它提供了一个方便的地方来限制x1、x2等的类型

我以前在哈斯克尔从没见过这样的把戏。以下是我真正遇到的问题:

  • 为什么这种类型声明的语法甚至存在?它能为我做什么,而下面的人却做不到

    prop_RevRev :: [Int] -> Bool
    prop_RevRev xs = reverse (reverse xs) == xs
    
  • 的这种用法是否构成了类型声明的“特殊”语法?或者它是一致的和合乎逻辑的(如果是,如何?)

  • 这是标准用法还是常规用法


  • 其中
    不是类型声明的特殊语法。例如,这项工作:

    prop_RevRev :: [Int] -> Bool
    prop_RevRev xs = ys == xs
      where ys = reverse (reverse xs)
    
    这也是:

    prop_RevRev xs = ys == xs
      where ys = reverse (reverse xs)
            ys :: [Int]
    
    where type=(xs::[Int])
    优于
    prop\u revrevrev::[Int]->Bool
    的优点是,在后一种情况下,您必须指定返回类型,而在前一种情况下,编译器可以为您推断返回类型。如果您有一个非
    Boolean属性,这将很重要,例如:

    prop_positiveSum xs = 0 < length xs && all (0 <) xs ==> 0 < sum xs
      where types = (xs :: [Int])
    
    read "Just True" :: (Maybe Bool)
    
    prop_positiveSum xs=0
    它没有特殊语法,有时您只需要它,如以下情况:

    foo :: String -> String
    foo s = show (read s)
    
    目前,无法键入该类型,因为无法识别值
    read s
    的类型。已知的是,它必须是Show和read的实例。但该类型根本不会出现在类型签名中,因此也不可能保留该类型并推断出受约束的类型。(只是没有可以约束的类型变量。)

    值得注意的是,
    reads
    的功能完全取决于给
    reads
    的类型签名,例如:

    prop_positiveSum xs = 0 < length xs && all (0 <) xs ==> 0 < sum xs
      where types = (xs :: [Int])
    
    read "Just True" :: (Maybe Bool)
    
    将成功,而

    read "Just True" :: (Maybe Int)
    

    不会。

    我也一直在想这个问题。谢谢。@MattFenwick:您可以在任何级别向任何子表达式添加类型批注,因此,当您只想填写编译器无法推断的细节,而不必指定完整的类型签名时,此技巧非常有用。但是,它们仍然必须保持一致例如,
    (x::Float)+(x::Int)
    将导致类型错误。因此基本上,
    类型
    类型
    是一个虚拟变量,不使用;只是为了方便另一个类型的保护expression@newacct:是,但不能使用
    类型
    ,因为这是保留关键字:)