Унифицированный интерфейс между функциями с разным количеством аргументов
У меня есть две функции, подобные этим:
foo :: a -> b -> x -> x
bar :: c -> y -> y
Я хотел бы объединить их в единый интерфейс, чтобы они оба могли иметь одинаковое имя. В моем случае это гарантировано, что типы x
а также y
разные (но может быть несколько x
"S). Так что это выглядит возможным. But all my attempts have bad type inference in case of partial application:(
Could you help to come up with interface for this case?
My previous attempts look like this but this solution requires explicit type application to disambiguate cases:
class Insert s i where
insert :: i
instance (Ord k, i ~ (k -> Set k -> Set k)) => Insert Set i where
insert = Set.insert
1 ответ
Я думаю, что следующее, вероятно, работает. Согласно комментариям, это все еще ужасная, ужасная, ужасная идея. Если вы действительно хотите писать на Haskell, то на самом деле вы не хотите писать на Haskell.
В любом случае, идея состоит в том, чтобы предоставить класс типа для:
insert :: (Ord k) => k -> v -> a
параметризован во всех трех параметрах с функциональной зависимостью, указывающей, что a
определяет k
а также v
, В твоем случае, a ~ (Map k' v' -> Map k' v')
подразумевает k ~ k'
а также v ~ v'
, в то время как a ~ Set t
подразумевает k ~ t
а также v ~ Set t
,
{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, FunctionalDependencies,
NoMonomorphismRestriction #-}
module UnifiedInsert where
-- insert :: Ord k => k -> v -> Map k v -> Map k v
-- insert :: Ord a => a -> Set a -> Set a
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Set (Set)
import qualified Data.Set as Set
class Insert k v a | a -> k, a -> v where
insert :: (Ord k) => k -> v -> a
instance Insert k (Set k) (Set k) where
insert = Set.insert
instance Insert k v (Map k v -> Map k v) where
insert = Map.insert
fromList = foldr insert mempty
foo1 :: Set Int
foo1 = fromList [1..10]
Обратите внимание, что средство проверки типа может определить тип функции fromList
(даже если foo1
удаляется из программы), пока ограничение мономорфизма отключено. Это будет иметь довольно нелепый тип:
fromList :: (Foldable t, Insert k v v, Ord k, Monoid v) => t k -> v
которые действительно могут быть специализированы для Ord a => [a] -> Set a
, как требуется.