Конечно, вы можете определить функцию сложения с вариациями с помощью некоторого хакерского типа: 1
{-# LANGUAGE TypeFamilies #-}
class Add r where
add' :: (Integer -> Integer) -> r
instance Add Integer where
add' k = k 0
instance (n ~ Integer, Add r) => Add (n -> r) where
add' k m = add' (\n -> k (m+n))
add :: (Add r) => r
add = add' id
И так:
GHCi> add 1 2 :: Integer
3
GHCi> add 1 2 3 :: Integer
6
Тот же трюк используется стандартным модулем Text.Printf
. Обычно этого избегают по двум причинам: во-первых, с типами, с которыми он работает, работать неудобно, и вам часто приходится указывать явную сигнатуру типа для вашего использования; во-вторых, это действительно взлом, и его следует использовать редко, если вообще. printf
должен принимать любое количество аргументов и быть полиморфными, поэтому он не может просто взять список списков, но для дополнения вы можете просто использовать sum
.
1 Расширение языка здесь не является строго необходимым, но оно облегчает использование (без них вам пришлось бы явно указывать тип каждого аргумента в приведенных мной примерах, например add (1 :: Integer) (2 :: Integer) :: Integer
). * * тысячу двадцать-один