haskell - 我怎样才能写出这个模式同义词而没有歧义的类型错误?

标签 haskell pattern-synonyms

使用 ViewPatternsData.Typeable ,我已经设法编写了一个函数,该函数允许我编写类似于类型案例分析的内容。观察:

{-# LANGUAGE GADTs, PatternSynonyms, RankNTypes, ScopedTypeVariables
           , TypeApplications, TypeOperators, ViewPatterns #-}

import Data.Typeable

viewEqT :: forall b a. (Typeable a, Typeable b) => a -> Maybe ((a :~: b), b)
viewEqT x = case eqT @a @b of
  Just Refl -> Just (Refl, x)
  Nothing -> Nothing

evilId :: Typeable a => a -> a
evilId (viewEqT @Int -> Just (Refl, n)) = n + 1
evilId (viewEqT @String -> Just (Refl, str)) = reverse str
evilId x = x

以上evilId函数确实非常邪恶,因为它使用 Typeable彻底颠覆参数化:
ghci> evilId True
True
ghci> evilId "hello"
"olleh"

由于我喜欢作恶,我对此很满意,但是上面的语法很嘈杂。我希望能够更清楚地编写相同的代码,因此我决定编写一个模式同义词:
pattern EqT :: forall b a. (Typeable a, Typeable b) => (a ~ b) => b -> a
pattern EqT x <- (viewEqT @b -> Just (Refl, x))

我想我可以使用这个模式同义词来使我的邪恶案例分析更容易阅读:
evilId :: Typeable a => a -> a
evilId (EqT (n :: Int)) = n + 1
evilId (EqT (str :: String)) = reverse str
evilId x = x

可悲的是,这根本不起作用。 GHC 在对模式进行类型检查之前似乎没有引用我的类型注释,因此它认为 b在每个模式中都是一个不明确的变量。有什么方法可以用模式同义词干净地包装这些模式,还是会被我的长 View 模式卡住?

最佳答案

如果目标是找到一些干净的语法来实现您的 evilId函数,你可以这样写:

{-# Language ScopedTypeVariables, GADTs, TypeApplications #-}

module Demo where

import Data.Typeable

evilId :: forall a. Typeable a => a -> a
evilId x
  | Just Refl <- eqT @a @Int    = x+1
  | Just Refl <- eqT @a @String = reverse x
  | otherwise                   = x

不幸的是,这对解决模式同义词的歧义没有帮助。

关于haskell - 我怎样才能写出这个模式同义词而没有歧义的类型错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41753345/

相关文章:

Haskell "No instance for"错误

haskell - 在表达式的情况下与已分配的变量匹配

haskell - 模式同义词导致不详尽的模式匹配

向量上的 Haskell 模式匹配

haskell - 如何从 Test.QuickCheck 显式导入 'Fn' 模式?

haskell - 私有(private)数据构造函数上的模式匹配

Haskell:Map.empty 出现 "Qualified name in binding position"错误

haskell - 将树转换为函数图库树的优雅方法?

haskell - 数据 (->) a b 是什么意思?

haskell - 不在数据构造函数范围内