如何声明参数可为(Int, Int)或Maybe (Int, Int)的Haskell函数?
实现支持两种类型参数的Haskell函数
当然可行,你当前的类型声明存在语法错误——Either是二元类型构造器,必须接受两个类型参数,你写的Either (Int, Int) Maybe (Int, Int)不符合这个规则,正确的写法需要把Maybe (Int, Int)作为第二个参数整体传入Either。下面提供几种实现方式:
方案1:直接使用Either类型
这是最直接的方式,用Either的Left分支承载(Int, Int),Right分支承载Maybe (Int, Int):
randomFunction :: [Char] -> [[Int]] -> Either (Int, Int) (Maybe (Int, Int)) -> Bool randomFunction _ _ (Left (x, y)) = x > y -- 处理纯(Int, Int)参数 randomFunction _ _ (Right Nothing) = False -- 处理Maybe (Int, Int)为Nothing的情况 randomFunction _ _ (Right (Just (x, y))) = x + y > 10 -- 处理Just包裹的(Int, Int)
调用示例:
-- 传入(Int, Int) randomFunction "test" [[1,2]] (Left (3, 5)) -- 传入Maybe (Int, Int) randomFunction "test" [[1,2]] (Right (Just (6, 7))) randomFunction "test" [[1,2]] (Right Nothing)
方案2:自定义代数数据类型
如果觉得Either的语义不够直观,可以自定义一个数据类型,明确区分两种参数场景:
-- 自定义类型,清晰标注两种参数形式 data ParamType = PlainPair (Int, Int) | MaybeWrappedPair (Maybe (Int, Int)) randomFunction :: [Char] -> [[Int]] -> ParamType -> Bool randomFunction _ _ (PlainPair (x, y)) = x * y /= 0 randomFunction _ _ (MaybeWrappedPair Nothing) = True randomFunction _ _ (MaybeWrappedPair (Just (x, y))) = x `mod` y == 0
调用示例:
randomFunction "test" [[1,2]] (PlainPair (3, 5)) randomFunction "test" [[1,2]] (MaybeWrappedPair (Just (6, 3)))
方案3:用类型类实现无包裹调用
如果希望直接传入(Int, Int)或Maybe (Int, Int)而不需要手动包裹构造器,可以用类型类实现:
class ConvertibleToParam a where toParam :: a -> ParamType instance ConvertibleToParam (Int, Int) where toParam = PlainPair instance ConvertibleToParam (Maybe (Int, Int)) where toParam = MaybeWrappedPair randomFunction :: ConvertibleToParam p => [Char] -> [[Int]] -> p -> Bool randomFunction s xs p = case toParam p of PlainPair (x, y) -> length s + sum (concat xs) > x + y MaybeWrappedPair Nothing -> False MaybeWrappedPair (Just (x, y)) -> x > y
调用示例:
-- 直接传入(Int, Int) randomFunction "test" [[1,2]] (3, 5) -- 直接传入Maybe (Int, Int) randomFunction "test" [[1,2]] (Just (6, 7)) randomFunction "test" [[1,2]] Nothing
内容的提问来源于stack exchange,提问作者Hector
相关产品推荐
相关产品推荐

