不同数量参数的函数之间的统一接口

Unified interface between functions of different number of arguments

我有两个这样的函数:

foo :: a -> b -> x -> x
bar :: c -> y -> y

我想将它们统一到一个界面中,这样它们就可以同名了。在我的例子中,保证 xy 类型不同(但可能有多个 x)。所以它看起来是可能的。但是在部分应用的情况下,我所有的尝试都有错误的类型推断:(

你能帮忙想出这个案例的界面吗?

我以前的尝试是这样的,但这个解决方案需要明确的类型应用程序来消除歧义:

class Insert s i where
  insert :: i

instance (Ord k, i ~ (k -> Set k -> Set k)) => Insert Set i where
  insert = Set.insert

我猜下面的方法可能有效。根据评论,这仍然是一个糟糕、糟糕、糟糕的想法。如果你真想这样写Haskell,那你就真的不想写Haskell.

无论如何,我们的想法是为class提供一个类型:

insert :: (Ord k) => k -> v -> a

在所有三个参数中进行参数化,并指定 a 确定 kv 的函数依赖性。在您的情况下,a ~ (Map k' v' -> Map k' v') 表示 k ~ k'v ~ v',而 a ~ Set t 表示 k ~ tv ~ 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