类型同义词的部分应用

Partial application of type synonyms

我在以下示例中遇到了不饱和类型同义词的问题:

{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE LiberalTypeSynonyms #-}

module TypeFamilyHackery where

data T k v a = T

type family CollectArgTypes arr where
  CollectArgTypes (a -> b) = (a, CollectArgTypes b)
  CollectArgTypes _ = ()

type family MapReturnType f t where
  MapReturnType f (a -> b) = a -> MapReturnType f b
  MapReturnType f r = f r

type MkT k v = T k v v

-- | Goal:
-- @
--   BuryT Int = T () Int Int
--   BuryT (Bool -> Int) = Bool -> T (Bool, ()) Int Int
--   BuryT (a -> b -> c) = a -> b -> T (a,(b,())) c c
-- @
type BuryT t = MapReturnType (MkT (CollectArgTypes t)) t

但这与 The type synonym 'MkT' should have 2 arguments, but has been given 1 相呼应。我可以将 MapReturnType 专门化为 MkT (CollectArgTypes t),但我更喜欢它的现状。

由于 -XLiberalTypeSynonyms 似乎没有交付(为什么?),我有什么选择可以让 BuryT 工作?

LiberalTypeSynonyms 通过内联所有“显而易见的”类型定义来工作。为了让你的例子工作,它必须

  1. 先把MapReturnType (MkT (CollectArgTypes t)) t当作一些MapReturnType ㄊ t
  2. 使用定义 MapReturnType f r = f r
  3. 将其内联到 ㄊ t
  4. 在这一点上,再次调用 将得到 MkT (CollectArgTypes t) t,这是一个非常好的完全应用的同义词,因此没有问题。

但是第 2 步是不可能的,因为 MapReturnType 而不是 只是一个同义词。要使用 MapReturnType f r = f r,编译器首先必须确保 r 不是函数类型,但它真的不知道这一点——毕竟它是一个完全自由的参数。

因此,编译器实际需要做的是,将 MapReturnType 的解析以及 BuryT 的解析延迟到具体的使用站点。现在,这可能非常有用,但它会打开一大堆蠕虫。也就是说,在你的程序类型中的任何地方都可以很容易地交织图灵完备程序。我认为这不值得。