类型实例中的等式约束

时间:2016-02-15 16:22:50

标签: haskell type-families

假设我有以下内容:

type family TF a b

我可以写这样的东西

type instance TF Int t = (t ~ (x,y)) => (Int,x,y)

可能是一个愚蠢的例子。

此问题的主题与此问题的接受答案相同:Haskell: Equality constraint in instance

我希望匹配类型实例,即使我不确定第二个参数是一对,然后强制第二个参数成为一对(如果这不成功则产生编译错误。)

1 个答案:

答案 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