Haskell ScopeTypeVariables无法帮助推断
我有一个通过sum类型转发type类方法调用的小实用函数。问题是我必须使用代理显式地传递约束。我只想使用ScopedTypeVariables 这是密码Haskell ScopeTypeVariables无法帮助推断,haskell,Haskell,我有一个通过sum类型转发type类方法调用的小实用函数。问题是我必须使用代理显式地传递约束。我只想使用ScopedTypeVariables 这是密码 {-# LANGUAGE TypeOperators #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module Mitsuba.Generic where
import GHC.Generics
import Data.Proxy
class GFold f c b where
genericFold :: p c -> (forall e. c e => e -> b) -> f a -> b
instance GFold a c d => GFold (M1 x y a) c d where
genericFold p f (M1 x) = genericFold p f x
instance ( GFold a c d
, GFold b c d
) => GFold (a :+: b) c d where
genericFold p f = \case
L1 x -> genericFold (Proxy :: Proxy c) f x
R1 x -> genericFold (Proxy :: Proxy c) f x
instance c a => GFold (K1 i a) c d where
genericFold p f (K1 x) = f x
gfold :: (Generic a, GFold (Rep a) c d)
=> p c -> (forall e. c e => e -> d) -> a -> d
gfold p h x = genericFold p h $ from x
data Foo = I Int | D Double | B Bool
deriving(Generic)
test :: String
test = gfold (Proxy :: Proxy Show) show $ I 1
所以测试工作就像我希望的那样。但是,我希望“gfold”函数如下所示
gfold :: forall a c d. (Generic a, GFold (Rep a) c d)
=> (forall e. c e => e -> d) -> a -> d
gfold h x = genericFold (Proxy :: Proxy c) h $ from x
进行编译,但测试会给出以下错误
src/Generic.hs:39:8:
Could not deduce (c0 Bool, c0 Double, c0 Int)
arising from a use of `gfold'
In the expression: gfold show
In the expression: gfold show $ I 1
In an equation for `test': test = gfold show $ I 1
src/Generic.hs:39:14:
Could not deduce (Show e) arising from a use of `show'
from the context (c0 e)
bound by a type expected by the context: (c0 e) => e -> String
at src/Mitsuba/Generic.hs:39:8-17
Possible fix:
add (Show e) to the context of
a type expected by the context: (c0 e) => e -> String
In the first argument of `gfold', namely `show'
In the expression: gfold show
In the expression: gfold show $ I 1
无论如何,我可以编写我想要的gfold版本吗?我认为在这种情况下,你不能将
c
与Show
统一起来,因为Show
不是中匹配c
的唯一可能约束(对于所有e.c e=>e->d)
。它也可以是其他类型的类,这意味着Show
,例如:
class Show a => MyShow a where
myShow :: a -> String
myShow a = "foo: " ++ show a
instance MyShow Int
instance MyShow Double
instance MyShow Bool
现在呢
test = gfold (Proxy :: Proxy MyShow) show $ I 1
还有类型检查。我不知道对
gfold
函数使用更明确的具体类型签名是否会违背您尝试执行的目的,但您可以使用更通用的gfold
版本进行测试类型检查,如下所示:
test::String
test=(gfold::((对于所有e.Show e=>e->String)->Foo->String))Show$I 1
它没有被称为任何类型的XScopedTypeLevelVariables
。@LeftAround关于这个解释是有道理的,但不幸的是,你不能用任何东西统一c
,你甚至不能为所有c d编写func=undefined::函数。(对于所有e.c.e=>e->d)
。传递给gfold
的函数在c
中必须是完全多态的,这实际上是没有意义的。这不会为我检查后一版本的gfold
。对gfold
的更改不是为了避免传递代理参数吗?