类型同义词的部分应用

时间:2017-09-13 16:52:08

标签: haskell ghc type-families partial-application 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工作吗?

1 个答案:

答案 0 :(得分:4)

LiberalTypeSynonyms通过内联所有“明显的”类型定义来工作。为了使您的示例有效,它必须

  1. 首先将MapReturnType (MkT (CollectArgTypes t)) t视为某些MapReturnType ㄊ t
  2. 使用定义ㄊ t
  3. 将其内联到MapReturnType f r = f r
  4. 此时,再次调用会给MkT (CollectArgTypes t) t这是一个非常完美的完全应用的同义词,因此没问题。
  5. 但是第2步是不可能的,因为MapReturnType 不是只是一个同义词。要使用MapReturnType f r = f r,编译器首先必须确保r不是函数类型,但它实际上无法知道这一点 - 它毕竟是一个完全自由的参数。

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