Могу ли я назвать подпись функции? - PullRequest
10 голосов
/ 18 июня 2011

Я передаю частично примененную функцию. Полная подпись:

import Data.Map as Map 
-- Update the correct bin of the histogram based on the min value, bin width,
-- the histogram stored as a map, and the actual value we are interested in.
updateHist :: Double -> Double -> Map.Map Bin Double -> Double -> 
              Map.Map Bin Double

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

-- Extra the data out of the string and update the histogram (in the Map) with it.
doSomething :: String -> (Map.Map Bin Double -> Double -> Map.Map Bin Double) -> 
               Map.Map Bin Double

Это все прекрасно, но писать "(Map.Map Bin Double -> Double -> Map.Map Bin Double)" довольно многословно. Я хотел бы заменить их все на «UpdateHistFunc» как тип, но по какой-то причине я продолжаю терпеть неудачу.

Я пытался:

newtype UpdateHistFunc = Map.Map Bin Double -> Double -> Map.Map Bin Double

Это не удалось с ошибкой:

HistogramForColumn.hs: 84: 44: ошибка анализа при вводе `-> '

Что я делаю не так?

1 Ответ

17 голосов
/ 18 июня 2011

Вы путаете type и newtype здесь?

Использование type определяет синоним типа, который, как вы, похоже, пытаетесь сделать, тогда как newtype создает новый тип, которому нужно имя конструктора, как с data.

Другими словами, вы, вероятно, хотите это:

type UpdateHistFunc = Map.Map Bin Double -> Double -> Map.Map Bin Double

... или, может быть, это:

newtype UpdateHistFunc = UpdateHistFunc (Map.Map Bin Double -> Double -> Map.Map Bin Double)

Последний, очевидно, должен быть "развернут", чтобы применить функцию.


Для справки:

  • data определяет новый алгебраический тип данных, который может быть рекурсивным, иметь отдельные экземпляры классов типов, вводить дополнительный слой возможной лени, и все такое.
  • newtype определяет тип данных с одним конструктором, принимающим один аргумент, который может быть рекурсивным и иметь разные экземпляры, но только для проверки типа; после компиляции он эквивалентен типу, который он содержит.
  • type определяет синоним типа, который не может быть рекурсивным или иметь отдельные экземпляры, полностью раскрывается при проверке типа и составляет чуть больше, чем макрос.

Если вас интересует семантическое различие между data и newtype в том, что касается "дополнительной лени", сравните эти два типа и возможные значения, которые они могут иметь:

data DType = DCon DType

newtype NType = NCon NType

Например, как вы думаете, что эти функции будут делать, если их применить к undefined против DCon undefined и NCon undefined соответственно?

fd (DCon x) = x
fn (NCon x) = x
...