Начальная точка:
fn :: [a] -> Int
fn = (2 *) . length
Предположим, что мы хотим ограничить возвращаемое значение, тогда мы могли бы написать:
fn list = (2 * length list) :: Int
Как насчет ограничения только аргумента? Легко.
fn list = 2 * length (list :: [Char])
Пока это работает, было бы предпочтительнее иметь подписи в верхней части собраны и не рассеяны вокруг тела функции.
Это самое близкое, что я могу придумать:
fnSig = undefined :: [Char] -> a
fn | False = fnSig
| True = (* 2) . length
На основе http://okmij.org/ftp/Haskell/partial-signatures.lhs через http://okmij.org/ftp/Haskell/types.html#partial-sigs
Тем не менее, я хотел бы получить более чистое решение. Что-то, что сообщает, что мое намерение является частичным ограничением. Что-то вроде этого, например:
fn :: [Char] -> a
fn = (2 *) . length
Или, может быть:
fn :: [Char] -> _
fn = (2 *) . length
Возможно ли это?
Изменить для дальнейшего уточнения:
@GaneshSittampalam Сделал важный момент в комментарии ниже. Я ищу "дом на полпути между подписью типа и вообще должен дать точный". Итак, я не ищу ответ на основе TypeClass, я просто хочу, чтобы GHC заполнил пробелы для неопределенных (или не полностью ограниченных) типов моей функции.
Изменить в ответ на @WillNess
Да, что-то вроде этого...
fn list = 2 * length list
where
_ = list :: [Char]
... может работать, но только для аргументов, и только если функция не является точечной. Есть ли способ применить этот метод к бесцентровым функциям или возвращать значения?
Изменить в ответ на @Rhymoid
Я получил вдохновение и поиграл с идеей @Rhymoid и придумал это:
fn = (2 *) . length
where
_ = fn `asTypeOf` (undefined :: [Char] -> a)
_ = fn `asTypeOf` (undefined :: a -> Int)
_ = fn `asTypeOf` (undefined :: a -> b)
_ = fn `asTypeOf` (undefined :: a)
Этот подход также ограничивает подпись типа fn и не загрязняет какое-либо пространство имен.
Обычно у нас будет только одна из строк asTypeOf
, я просто добавил несколько, чтобы продемонстрировать, насколько мощный этот подход.
Это немного более неуклюжий, чем то, как я бы хотел, но я думаю, что это довольно аккуратно, мы можем сделать это даже без специальной синтаксической поддержки с языка.
@Rhymoid, если вам это нравится, добавьте его в свой ответ.:)