我有两个类似的功能:
foo :: a -> b -> x -> x
bar :: c -> y -> y
我想将它们统一为一个接口,以便它们可以具有相同的名称。在我的情况下,可以保证类型x
和y
是不同的(但可能有多个x
)。因此,这似乎是可能的。但是在部分应用的情况下,我所有的尝试都具有错误的类型推断:(
在这种情况下,您能帮忙提出一个界面吗?
我以前的尝试是这样的,但是此解决方案需要显式类型应用程序才能消除歧义:
class Insert s i where
insert :: i
instance (Ord k, i ~ (k -> Set k -> Set k)) => Insert Set i where
insert = Set.insert
答案 0 :(得分: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
。