【问题标题】:How to return different type in recursion function? (Haskell)如何在递归函数中返回不同的类型? (哈斯克尔)
【发布时间】:2019-03-19 12:31:42
【问题描述】:

我需要在递归函数中返回例如整数或布尔值。

我的问题的示例代码:

findInt :: [Int] -> Either Int Bool
findInt (x:xs) =
     if x == 1 then x
     else False : findInt xs

然后错误显示无法将预期类型“Either Int Bool”与实际类型“Int”匹配。但是我想检查该元素是否在此列表中,如果存在,它将返回该元素并通过返回布尔值告诉我它是否不在。

【问题讨论】:

  • 如果您添加了一些输入示例和您期望的相应输出,例如findInt [...] == ... 用于各种情况,那么回答您的问题会更容易。
  • 事实上,你的函数说“给定一个至少包含一个元素的列表,如果第一个元素是整数 1,则返回该整数,否则返回一个以布尔值 False 开头的列表接下来是在列表的其余部分调用findInt 的结果;当给定一个空列表时,引发一个错误”,这没有多大意义,所以很难确定你想做什么来帮助你。

标签: haskell recursion types return-type


【解决方案1】:

如果您查看Either 类型,您会发现它有两个构造函数,LeftRight。为了构造Either 类型的值,您需要使用其中一个构造函数。例如

if x == 1 then Left x

具体来说,Left 用于构造 Either 类型的第一种类型(本例中为 Int),Right 用于构造第二种类型(本例中为Bool)。

【讨论】:

  • 啊谢谢你指出这一点!但是现在我有另一个错误,它也与预期类型不匹配,无法将预期类型“Either Int Bool”与实际类型“[Either a0 Bool]”匹配
  • 这个问题可能与 findInt 的签名说它返回单个值有关,但实际上它可以返回一个列表(在 else 行)。
  • 我已经回滚了,因为我已经发布了自己的答案。
【解决方案2】:

你给定的函数没有类型:x :: Int(False : _) :: [Bool],这两种类型不能统一(将::读作“有类型”)。

调整,

findInt (x:xs) =
     if x == 1 then Left x
     else Right False : findInt xs

还是没有类型:Left x :: Either Int b(Right False : _) :: [Either a Bool],这两种类型也不能统一。

但是

findInt :: [Int] -> Either Int Bool
findInt (x:xs) =
     if x == 1 then Left x
     else findInt xs
findInt [] = Right False

有一个类型,因为Left x :: Either Int bRight False :: Either a Bool,而这两种类型可以统一起来:

        Either Int b
        Either a   Bool
       -----------------      a ~ Int , b ~ Bool
        Either Int Bool

统一类型确实是Either Int Bool,正如类型签名所指定的那样。

【讨论】:

  • 此外,由于Right x 仅与x=False 一起使用,所以Either Int Bool 类型比需要的更复杂,可能应该用Maybe Int 替换,相应地调整代码。跨度>
  • @chi 你的意思是“也许是 1”,即Bool
  • 不,我的意思是Maybe Int。关键是Either Int Bool 同构于Int 加上两个“特殊”值(Right True, Right False)。尽管如此,上面的代码只使用了一个特殊值(Right False),所以我们可以从类型中删除另一个未使用的(Right True)。因此,我们得到Maybe Int,我们可以让findInt (x:xs) = if x==1 then Just x else findInt xs ; findInt [] = Nothing
  • @chi 由于唯一返回的Int 值是1,它可以从Maybe Int 进一步简化为Bool,其中Just 1 对应于True,而@ 987654351@对应False
  • @4castle 啊,我现在明白威尔的意思了。谢谢。我同意:那么它应该是Bool。 (不知何故,我想知道这是否是 OP 真正想要的。)
【解决方案3】:

由于您从未在输出中使用True,因此您对Either Int Bool 的使用与Maybe Int 同构:

a2b :: Either Int Bool -> Maybe Int
a2b (Right x) = Just x
a2b (Left x) = Nothing

b2a :: Maybe Int -> Either Int Bool
b2a (Just x) -> Right x
b2a Nothing -> Left False

因此,我只想使用Maybe Int 来简化您的功能。

findInt :: [Int] -> Maybe Int
findInt [] = Nothing
findInt (x:xs) = if x == 1 then Just x else findInt xs

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-16
    相关资源
    最近更新 更多