haskell - 比较haskell中的输入
问题描述
我确实想在以下函数中获取一个元组 (String, Int) 和另一个值 a 作为我的输入:
getOtherPairValue :: Eq a => (String, Int) -> a -> Either a (b, a)
我想将输入 a 与我的元组进行比较,如果我的元组中的第一个元素与输入 a 不匹配,我想检查它是否与第二个元素匹配。如果它根本不匹配,我确实想按原样返回元组。
如果输入 a 与字符串或整数匹配,我想返回元组的不匹配元素。
我尝试了以下功能:
getOtherPairValue (s, i) e
| e == i = Left s
| e == s = Left i
| e /= s && e /= i = Right (s, i)
解决方案
在开始之前,让我告诉你,这对我来说是一个可怕的想法。您要求一个函数采用必须是字符串或整数的参数,然后返回“另一种类型”,并且可以处理在类型化语言中的工作。
我们在 Haskell 中确实有一些可以实现类似的东西,但我想知道你是否真的需要首先这样做。
反正:
利用Either
getOtherPairValue :: (String, Int) -> Either String Int
-> Either String (Either Int (String, Int))
getOtherPairValue (s, i) (Left e) | e == s = Right (Left i)
getOtherPairValue (s, i) (Right e) | e == i = Left s
getOtherPairValue p _ = Right (Right p)
Either
注意函数返回的嵌套。这是必需的,因为我们必须返回一个字符串、一个整数或一对。也许返回自定义总和类型是明智的。
修补类型级机械
这是一个矫枉过正的解决方案。
我们首先定义“元组中的另一种类型是什么”
type family Other a where
Other String = Int
Other Int = String
然后,我们使用Typeable
在运行时检查类型是否相同:
getOtherPairValue :: forall a. Typeable a
=> (String, Int) -> a -> Either (Other a) (String, Int)
getOtherPairValue p@(s, i) x = case (eqT @a @String, eqT @a @Int) of
(Just Refl, _) | x == s -> Left i
(_, Just Refl) | x == i -> Left s
_ -> Right p
这涉及类型族、GADT 和Typeable
. 对我来说,这个操作看起来非常复杂,而这种复杂性是由于必须实现一个不能很好地处理类型的函数。
推荐阅读
- android - unity AAB + PAD 方法不构建。(安卓应用)
- android - Android jni框架内部类初始化及使用帮助需要
- excel - PtrSafe 子声明?
- spring - How does Spring (Boot) work with Pageable in controllers method argument?
- javascript - 如何限制要搜索的电子邮件数量?
- android - 尝试在前台启动时出现 Android 服务段错误
- reactjs - 您可能需要适当的加载器来处理此文件类型,目前没有配置加载器来处理此文件(.css、.png、.html)
- unit-testing - 使用单元测试(Jest)问题运行 cypress
- python - 如何从 Python 解释器获取 GCC 样式的行注释错误消息?
- php - PHP 7.4 字符串比较