假设我有以下内容:
type family TF a b
我可以写这样的东西
type instance TF Int t = (t ~ (x,y)) => (Int,x,y)
可能是一个愚蠢的例子。
此问题的主题与此问题的接受答案相同:Haskell: Equality constraint in instance
我希望匹配类型实例,即使我不确定第二个参数是一对,然后强制第二个参数成为一对(如果这不成功则产生编译错误。)
答案 0 :(得分:4)
您可以使用新的TypeError功能在GHC 8.0中执行此操作,具体取决于您的意思"强制第二个参数为一对"。
{-# LANGUAGE TypeFamilies, DataKinds, TypeOperators, UndecidableInstances #-}
module Pair where
import GHC.TypeLits
type family Fst p where
Fst (x, y) = x
Fst _t = TypeError (Text "Fst: expected a pair, but got " :<>: ShowType _t)
type family Snd p where
Snd (x, y) = y
Snd _t = TypeError (Text "Snd: expected a pair, but got " :<>: ShowType _t)
type family TF a b
type instance TF Int t = (Int, Fst t, Snd t)
现在,如果您尝试将TF Int
应用于非元组,则会出现编译错误:
*Pair> let x = x in x :: TF Int Bool
<interactive>:9:1: error:
• Fst: expected a pair, but got Bool
• When checking the inferred type
it :: (Int, (TypeError ...), (TypeError ...))
然而,这并不是真的“强迫”#34;成为一对的论点不仅仅是呼叫fromJust
&#34;强迫&#34;它的论点是Just x
形式。它实际上是在类型级别使用部分函数进行编程。
类型族应用程序的格式完全取决于类型族的类型,而(x, y)
对与*
具有相同类型Bool
。只需写下类型系列的应用程序,就无法神奇地产生约束。如果要在类型级别获取约束,则必须将其写入=>
的左侧。
在关联的问题中,CanFilter (b -> c) a
已经是一个约束,因此它可能意味着b ~ c
。