如何提升返回带有单例的String的函数?

时间:2017-10-19 16:07:49

标签: haskell singleton-type

使用堆栈与lts-9.2(和单例-2.1),我有这个:

   $(singletons [d|
       data EventScans
        = PassThrough
        | SuiteProgress

       -- cn :: EventScans -> [Char]
       cn PassThrough = "all-events"
       cn SuiteProgress = "suite-progress"
    |])

我不能给这个函数一个类型签名,推断的类型签名是cn :: IsString t => EventScans -> t。 AFAIK IsString不会单一化。

如果没有cn上的类型签名,我会按预期获得Cn类型系列。如果我尝试添加类型签名,我会得到:

* Expected kind `[Char]', but `"all-events"' has kind `Symbol'
* In the type `"all-events"'
  In the type family declaration for `Cn' (haskell-stack-ghc)

这样做的正确方法是什么?

修改如果我尝试添加类型签名cn :: IsString t => EventScans -> t,我会收到以下错误:

Variable `a_agPb' used as both a kind and a type
 Did you intend to use TypeInType? (haskell-stack-ghc)
Not in scope: type constructor or class `SIsString'
  Perhaps you meant `IsString' (imported from Data.String) (haskell-stack-ghc)

2 个答案:

答案 0 :(得分:0)

从我在github上打开的相关问题来看,这是因为mappedBy还没有单一化。有关详细信息,请参阅https://github.com/goldfirere/singletons/issues/267

答案 1 :(得分:0)

您需要通过执行以下操作来禁用OverloadedString,或者需要明确其类型:


$(singletons [d|
       data EventScans
        = PassThrough
        | SuiteProgress

       -- cn :: EventScans -> [Char]
       cn PassThrough = ("all-events" :: String)
       cn SuiteProgress = ("suite-progress" :: String)
    |])

我认为它不想这样做,因为现在您需要2层多态性(值和类型级别)。我怀疑您是否需要它,所以要明确一点。

但是您在这里所做的事情实际上并不需要单例。 单例仅是从值到类型的必要条件,在这种情况下,您知道所有值,因此可以返回到普通的类型家族:

{-# LANGUAGE FlexibleInstances   #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications    #-}
{-# LANGUAGE TypeFamilies        #-}

module Main where

import           Data.Proxy
import           GHC.TypeLits

test1 :: String
test1 = getStat $ Proxy @PassTrough

test2 :: String
test2 = getStat $ Proxy @SuiteProgress

data PassTrough
data SuiteProgress

type family Cn d :: Symbol where
  Cn PassTrough = "all-events"
  Cn SuiteProgress = "suite-progress"

getStat :: forall a b . ((Cn a) ~ b, KnownSymbol b) => Proxy a -> String
getStat _ = symbolVal $ Proxy @b