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

时间:2018-07-22 04:18:19

标签: haskell interface type-inference typeclass partial-application

我有两个类似的功能:

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

1 个答案:

答案 0 :(得分:1)

我想以下可能有效。根据评论,这仍然是一个可怕,可怕,可怕的想法。如果您真的想这样写Haskell,那么您真的不想写Haskell。

无论如何,该想法是为以下类型提供类型类:

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