Haskell - объявление типа нескольких функций

Я часто нахожу, что пишу несколько функций одного типа. Позвольте называть этот тип FuncType. Я мог бы написать что-то вроде этого:

funcA :: FuncType
funcB :: FuncType
funcC :: FuncType
funcD :: FuncType

-- Implementations

Это похоже на много ненужного ввода (набрав, как при нажатии на клавиатуре, а не объявлении типов функций). Может быть, есть способ сделать это более сжато? То, что я хочу, будет выглядеть примерно так:

(funcA, funcB, funcC, funcD) :: FuncType

-- Implementations

Я действительно пытался это сделать Google, но я вышел пустым. Если это не особенность языка, почему бы и нет? Я что-то упускаю? Я что-то делаю неправильно, если мне это нужно?

Ответ 1

Сделайте то, что вы пробовали без круглых скобок.

funcA, funcB, funcC, funcD :: FuncType

В отчете Haskell 2010 вы можете увидеть в главе 4 (Декларации и привязки), что (gendecl) выглядит следующим образом:

vars :: [context =>] type

и vars выглядят следующим образом:

var-1 , … , var-n

Это именно та форма, которую вы ищете.


Sidenote: Haddock будет применять документацию, если она найдет ее вокруг этой сигнатуры типа для каждого символа в этом списке (vars).

Ответ 2

В качестве альтернативы для ответа MasterMastic вы также можете дать повторяющееся имя типа с помощью объявления типа:

-- | why GoodName is a good name
type GoodName = Complicated -> Function -> Type

-- | Foo explanation.
foo :: GoodName
foo = ...

-- | Bar explanation.
bar :: GoodName
bar = ...

Таким образом, вам нужно только повторить имя вместо потенциально более длинного типа. Преимущества этого стиля над foo, bar :: Complicated -> Function -> Type включают:

  • именованный тип служит в качестве документации
  • именованный тип может быть повторно использован в другом месте
  • определения функций и сигнатуры типов находятся рядом друг с другом.
  • у вас могут быть разные комментарии пикши для различных функций
  • ваш исходный код выглядит более регулярным
  • Если только одна из функций позже получает рефакторинг для принятия дополнительных аргументов, изменение является более локальным.

Конечно, вы можете также объединить эти подходы как foo, bar :: GoodName. Из-за вывода типа вы обычно можете вообще исключить подпись типа и дать компилятору понять тип.