比较 haskell 中的输入
compairing inputs in haskell
我确实想获得一个元组 (String, Int) 和另一个值 a 作为我在以下函数中的输入:
getOtherPairValue :: Eq a => (String, Int) -> a -> Either a (b, a)
我想将输入 a 与我的元组进行比较,如果我的元组中的第一个元素与输入 a 不匹配,我想检查它是否与第二个元素匹配。如果它根本不匹配,我确实想要return原样的元组。
如果输入 a 与字符串或整数匹配,我想 return 我的元组的非匹配元素。
我尝试了以下功能:
getOtherPairValue (s, i) e
| e == i = Left s
| e == s = Left i
| e /= s && e /= i = Right (s, i)
在开始之前,让我告诉你,这对我来说是个糟糕的想法。您要求一个函数接受一个参数,该参数必须是字符串或整数,然后是 return“另一种类型”,并且可以处理类型化语言。
我们在 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
return。这是必需的,因为我们必须 return 一个字符串、一个整数或一对。也许 return 自定义总和类型会更明智。
修补类型级机械
这是一个矫枉过正的解决方案。
我们首先定义“元组中的其他类型是什么”
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
。对我来说,这个操作看起来非常复杂,这种复杂性是由于必须实现一个不能很好地处理类型的函数。
我确实想获得一个元组 (String, Int) 和另一个值 a 作为我在以下函数中的输入:
getOtherPairValue :: Eq a => (String, Int) -> a -> Either a (b, a)
我想将输入 a 与我的元组进行比较,如果我的元组中的第一个元素与输入 a 不匹配,我想检查它是否与第二个元素匹配。如果它根本不匹配,我确实想要return原样的元组。
如果输入 a 与字符串或整数匹配,我想 return 我的元组的非匹配元素。
我尝试了以下功能:
getOtherPairValue (s, i) e
| e == i = Left s
| e == s = Left i
| e /= s && e /= i = Right (s, i)
在开始之前,让我告诉你,这对我来说是个糟糕的想法。您要求一个函数接受一个参数,该参数必须是字符串或整数,然后是 return“另一种类型”,并且可以处理类型化语言。
我们在 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
return。这是必需的,因为我们必须 return 一个字符串、一个整数或一对。也许 return 自定义总和类型会更明智。
修补类型级机械
这是一个矫枉过正的解决方案。
我们首先定义“元组中的其他类型是什么”
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
。对我来说,这个操作看起来非常复杂,这种复杂性是由于必须实现一个不能很好地处理类型的函数。