我確實想在以下函式中獲取一個元組 (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)
uj5u.com熱心網友回復:
在開始之前,讓我告訴你,這對我來說是一個可怕的想法。您要求一個函式接受一個必須是字串或整數的引數,然后回傳“另一種型別”,并且可以處理型別化語言的作業。
我們在 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. 對我來說,這個操作看起來非常復雜,這種復雜性是由于必須實作一個不能很好地處理型別的函式。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/350269.html
