如何将类型级别列表转换为成对链

时间:2019-07-25 05:11:39

标签: haskell functional-programming singleton-type

没有强大的背景知识,单例库似乎很难处理。有什么方法可以将像'[1, 2, 3]这样的级别类型列表转换成像'(1, '(2, '(3, '())))这样的成对链?

我试图写几行,但是它们为我产生了无表情的错误。

{-# LANGUAGE TypeFamilies, TypeInType #-}

module ExpandList where

import Data.Singletons.Prelude.List
import Data.Singletons.Prelude.Tuple

type family IntoChainOfPairs (xs :: [k]) :: (k, b) where
  IntoChainOfPairs (x ': '[]) = '(x, '())
  IntoChainOfPairs (x ': xs) = '(x, IntoChainOfPairs xs)

sIntoChainOfPairs :: forall a (t :: [a]). Sing t -> Sing (IntoChainOfPairs t)
sIntoChainOfPairs = \case
  SCons a SNil -> STuple2 a STuple0
  SCons a b -> STuple2 a (sIntoChainOfPairs b)

所以我陷入了根本的误解。编译器不了解我,我不了解。我确定我的代码在根本上是错误的。

1 个答案:

答案 0 :(得分:2)

IntoChainOfPairs的结果类型应随输入而变化。因此,实际上有两个函数,一个type ToPairsType (xs :: [a]) :: Type(根据输入计算输出类型)和一个type ToPairs (xs :: [a]) :: ToPairsType xs(实际计算输出)。

type family ToPairsType (xs :: [a]) :: Type where
  ToPairsType '[] = ()
  ToPairsType ((_ :: a) : xs) = (a, ToPairsType xs)
type family ToPairs (xs :: [a]) :: ToPairsType xs where
  ToPairs '[] = '()
  ToPairs (x : xs) = '(x, ToPairs xs)

您定义了一个局部函数,其中bIntoChainOfPairs的参数。你真的写了

type family IntoChainOfPairs (k :: Type) (b :: Type) (xs :: [k]) :: (k, b) where
  IntoChainOfPairs k () (x : '[]) = '(x, '())
  IntoChainOfPairs k (k, b') (x : xs) = '(x, IntoChainOfPairs k b' xs)

您在b上进行了部分模式匹配,而在k上进行了非线性匹配。此外,不自然的(部分!)列表处理也无济于事。您可以使用case基础结构在Type上痛苦地获得Typeable的价值级别sIntoChainOfPairs,以编写IntoChainOfPairs,但我不建议这样做。真的,sToPairs刚刚坏了。

ToPairs被写为sToPairs :: forall (a :: Type) (xs :: [a]). Sing xs -> Sing (ToPairs xs) sToPairs SNil = STuple0 sToPairs (SCons x xs) = STuple2 x (sToPairs xs) 的直接“反射”:

func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
        do {
            try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, mode: AVAudioSessionModeDefault, options: [.mixWithOthers, .allowAirPlay])
            print("Playback OK")
            try AVAudioSession.sharedInstance().setActive(true)
            print("Session is Active")
        } catch {
            print(error)
        }
        return true
    }