Что означает?

Я пытаюсь выучить Хаскель.

Я читаю код здесь [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

2 ответа

Это означает "экспортировать все конструкторы и записи полей для этого типа данных".

При написании списка экспорта модулей есть три способа экспорта данных:

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

Синтаксис списков импорта / экспорта не имеет ничего общего с синтаксисом самого Haskell. Это просто разделенный запятыми список всего, что вы хотите экспортировать из вашего модуля. Теперь есть проблема, потому что на Хаскеле действительно есть два языка с символами, которые могут иметь одинаковое имя. Это особенно характерно для newtypeкак в вашем примере: у вас есть имя уровня типа SharedSeed :: *, а также имя уровня значения (конструктор данных) SharedSeed :: ByteString -> SharedSeed,

Это происходит только с заглавными именами, потому что строчные буквы на уровне типа всегда являются локальными переменными типа. Таким образом, соглашение в списках экспорта, что имена в верхнем регистре относятся к типам.

Но простой экспорт типа не позволяет пользователям фактически создавать значения этого типа. Это часто разумно: не все значения внутреннего представления могут принимать допустимые значения для нового типа (см . Пример Бартека), поэтому лучше экспортировать только безопасный умный конструктор вместо небезопасного конструктора данных.

Но в других случаях вы хотите сделать конструктор данных доступным, конечно, для мультиконструктивных типов, таких как Maybe, Для этого списки экспорта имеют три синтаксиса, которые вы можете использовать:

module Pos.Core.Types(
  • SharedSeed (SharedSeed) будет экспортировать конструктор SharedSeed, В этом случае это, конечно, единственный конструктор в любом случае, но если бы были другие конструкторы, они не экспортировались бы с этим синтаксисом.

  • SharedSeed (..) будет экспортировать все конструкторы. Опять же, в этом случае это только SharedSeedно, например, Maybe это будет экспортировать оба Nothing а также Just,

  • pattern SharedSeed будет экспортировать ShareSeed в качестве отдельного шаблона (независимо от экспорта ShareSeed тип). Это требует -XPatternSynonyms расширение.

    )
    
Другие вопросы по тегам