我知道TypeSynomymInstances只允许在实例头中使用完全应用的类型同义词,但是如果我可以使用paritally应用的类型同义词,它似乎也很方便.
例如:
class Example e where
thingy :: a -> b -> e a b
-- legit, but awkward
newtype FuncWrapper e a b = FuncWrapper { ap :: a -> e a b }
instance (Example e) => Example (FuncWrapper e) where
thingy _ = FuncWrapper . flip thingy
funcWrapperUse :: (Example e) => e Int String
funcWrapperUse = thingy 1 "two" `ap` 3 `ap` 4 `ap` 5
-- not legal, but a little easier to use
type FuncSynonym e a b = a -> e a b
instance (Example e) => Example (FuncSynonym e) where
thingy _ = flip thingy
funcSynonymUse :: (Example e) => e Int String
funcSynonymUse = thingy 1 "two" 3 4 5
Run Code Online (Sandbox Code Playgroud)
Hea*_*ink 31
Haskell中根本不允许部分应用的类型同义词.部分应用的同义词实际上是一个函数,其输入是未应用的类型,其输出是类型.例如,这是布尔逻辑的编码:
type True x y = x
type False x y = y
type Not b x y = b y x
type And b1 b2 x y = b1 (b2 x y) y
type Or b1 b2 x y = b1 x (b2 x y)
Run Code Online (Sandbox Code Playgroud)
要确定两个部分应用的类型同义词是否相等,类型检查器必须决定函数是否相等.这是一个难题,一般来说它是不可判定的.
允许部分应用类型同义词的另一个问题是它们会使类型推断和实例选择基本上不可能.例如,假设在某些程序的上下文中我想thingy在该类型中使用Int -> String -> Int -> (Int, String). thingy有类型forall a b e. a -> b -> e a b的,所以我们可以统一a使用Int,并b用String,但如果e被允许为部分应用型的代名词,我们可以有
e = FuncSynonym (,)
Run Code Online (Sandbox Code Playgroud)
要么
e = FuncSynonym' Int (,) where type FuncSynonym' x f a b = x -> f a b
Run Code Online (Sandbox Code Playgroud)
甚至
e = Const2 (Int -> (Int, String)) where Const2 a x y = a
Run Code Online (Sandbox Code Playgroud)
类型推断的问题会比决定函数的相等性更糟糕; 它需要考虑与特定输入指定的输出,或类似的更复杂的问题的所有功能(想象一下,无非是想统一a b使用Int).