级别列表'[a,b,c,...]来运行a

我有一个按类型列表索引的数据族,列表中的类型对应于数据实例的参数。 我想写的函数根据数据实例的不同而有不同的参数和参数,所以我可以使用它作为家族中每个数据实例的同义词。

{-# LANGUAGE KindSignatures, DataKinds, TypeOperators, 
             TypeFamilies, FlexibleInstances, PolyKinds #-}

module Issue where


type family (->>) (l :: [*]) (y :: *) :: * where
    '[]       ->> y = y
    (x ': xs) ->> y = x -> (xs ->> y)

class CVal (f :: [*]) where
    data Val f :: *
    construct :: f ->> Val f

instance CVal '[Int, Float, Bool] where
    data Val '[Int, Float, Bool] = Val2 Int Float Bool
    construct = Val2

这编译好。 但是当我尝试应用construct函数时:

v :: Val '[Int, Float, Bool]
v = construct 0 0 True

它会产生错误:

Couldn't match expected type `a0
                              -> a1 -> Bool -> Val '[Int, Float, Bool]'
            with actual type `f0 ->> Val f0'
The type variables `f0', `a0', `a1' are ambiguous
The function `construct' is applied to three arguments,
but its type `f0 ->> Val f0' has none
In the expression: construct 0 0 True
In an equation for `v': v = construct 0 0 True

你的代码不能检查,因为类型族不是(必然)是内射的。 如果你通过在f ->> Val f指定f的选择来帮助GHC f ->> Val f ,那么它按预期工作:

{-# LANGUAGE KindSignatures, DataKinds, TypeOperators, 
             TypeFamilies, FlexibleInstances, PolyKinds #-}

module Issue where

import Data.Proxy

type family (->>) (l :: [*]) (y :: *) :: * where
    '[]       ->> y = y
    (x ': xs) ->> y = x -> (xs ->> y)

class CVal (f :: [*]) where
    data Val f :: *
    construct :: proxy f -> f ->> Val f

instance CVal '[Int, Float, Bool] where
    data Val '[Int, Float, Bool] = Val2 Int Float Bool deriving Show
    construct _ = Val2

v :: Val '[Int, Float, Bool]
v = construct (Proxy :: Proxy '[Int, Float, Bool]) 0 0 True

关键是通过Proxy :: Proxy '[Int, Float, Bool]参数来construct ,从而修复f的选择。 这是因为没有任何东西让你f1类型f1f2 ,使得f1 ->> Val f1 ~ f2 ->> Val f2

别担心,这种语言的缺点正在被观察。

链接地址: http://www.djcxy.com/p/86101.html

上一篇: level list '[a,b,c,...] to function a

下一篇: Automatic derivation of Data.Vector.Unbox with associated type synonyms