Унифицированный интерфейс между функциями с разным количеством аргументов

У меня есть две функции, подобные этим:

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, как требуется.

Другие вопросы по тегам