6

我正在努力学习 Haskell。

我正在阅读此处[1] 上的代码。我只是从第 46 行和第 298-300 行复制并粘贴了部分代码。

问题: (..) 是什么意思?

我把它搞砸了,但我没有得到任何结果。

module Pos.Core.Types(
-- something here

 SharedSeed (..) -- what does this mean?

) where


newtype SharedSeed = SharedSeed
{ getSharedSeed :: ByteString
} deriving (Show, Eq, Ord, Generic, NFData, Typeable)

[1] https://github.com/input-output-hk/cardano-sl/blob/master/core/Pos/Core/Types.hs

4

2 回答 2

5

导入/导出列表的语法与 Haskell 本身的语法关系不大。它只是一个逗号分隔的列表,列出了您要从模块中导出的所有内容。现在,这里有一个问题,因为 Haskell 确实有两种语言的符号可能具有相同的名称。newtype这在您的示例中的 s中尤为常见:您有一个类型级别的名称 SharedSeed :: *,还有一个值级别的名称(数据构造函数)SharedSeed :: ByteString -> SharedSeed

这只发生在大写名称中,因为类型级别的小写始终是局部类型变量。因此,导出列表中的约定大写名称指的是类型

但是仅仅导出类型并不允许用户实际构造该类型的值。这通常是谨慎的:并非所有内部表示值都可能成为新类型的合法值(参见Bartek 的示例),因此最好只导出安全的智能构造函数而不是不安全的数据构造函数。

但其他时候,您确实希望使数据构造函数可用,当然对于多构造函数类型,如Maybe. 为此,导出列表具有您可以使用的三种语法:

module Pos.Core.Types(
  • SharedSeed (SharedSeed)将导出构造函数SharedSeed。在这种情况下,这当然是唯一的构造函数,但是如果有其他构造函数,它们就不会使用这种语法导出。

  • SharedSeed (..)将导出所有构造函数。同样,在这种情况下,这只是SharedSeed,但例如Maybe它会同时导出NothingJust

  • pattern SharedSeedShareSeed作为独立模式导出(独立于ShareSeed类型的导出)。这需要-XPatternSynonyms扩展名

    )
    
于 2017-08-02T12:10:59.290 回答
5

这意味着“导出此数据类型的所有构造函数和记录字段”。

在编写模块导出列表时,可以通过三种4方式导出数据类型:

module ModuleD(
    D,       -- just the type, no constructors
    D(..),   -- the type and all its constructors
    D(DA)    -- the type and the specific constructor
    ) where

data D = DA A | DB B

如果您不导出任何构造函数,那么至少不能直接构造类型。如果您想对数据类型强制执行一些运行时不变量,这很有用:

module Even (evenInt, toInt) where

newtype EvenInt = EvenInt Int deriving (Show, Eq)

evenInt :: Int -> Maybe EvenInt
evenInt x = if x `mod` 2 == 0 then Just x else Nothing

toInt :: EvenInt -> Int
toInt (EvenInt x) = x

调用者代码现在可以使用这种类型,但只能以允许的方式:

x = evenInt 2
putStrLn $ if isJust x then show . toInt . fromJust $ x else "Not even!"

作为旁注,toInt为方便起见,通常通过记录语法间接实现:

data EvenInt = EvenInt { toInt :: Int }

4查看@leftaroundabout的回答

于 2017-08-02T11:53:12.833 回答