【问题标题】:haskell, case of like fmaphaskell,类似 fmap 的情况
【发布时间】:2016-04-20 08:34:48
【问题描述】:

我有一个foo :: a -> a -> Either String TypeConstructor 类型的函数
foo 可以返回throwError StringTypeConstructor 的东西。

我想做类似fmap 的事情。我的意思是我想case (foo x y z) of ... 其中... 表示不同的值(它取决于foo 中使用的构造函数值)。

有没有办法做到这一点?

【问题讨论】:

  • Either 已经有一个 Functor 实例 - 所以如果你为 TypeConstructor 提供一个实例(这里是一个奇怪的名字) - 你可以只到 fmap . fmap

标签: haskell monads


【解决方案1】:

一种基本的方法是对所有内容进行模式匹配

case foo x y of
  Left string -> ...
  Right (Cons1 z w) -> ...
  Right (Cons2 a b c) -> ...
  Right Cons3 -> ...

其中Cons1, ...TypeConstructor 的值构造函数。

【讨论】:

  • 是的,但是我的错误不是“地下” - 这就是为什么我想使用类似fmap
  • @HaskellFun 那么恐怕我不能完全理解这个问题。也许您可以使用either 组合器来删除左/右模式匹配,但似乎您仍然需要为所有构造函数使用case
【解决方案2】:

不能直接写

case (foo x y) of ...

然后在TypeConstructor 的类型构造函数上进行模式匹配,因为foo x y 没有正确的类型(它是Either String TypeConstructor)。

但是,您可以在TypeConstructor 的类型构造函数上定义一个模式匹配的函数,然后在foo x y 的结果上定义fmap this ,如下所示。

import Control.Monad.Except (throwError)

data Type = Int Int
          | Str String
          deriving (Show)

foo :: Int -> String -> Either String Type
foo n s =
    if n == 0
        then throwError "Zero"
        else return (Str s)

bar x y = fmap f (foo x y)
    where
        f a = case a of
            Int n -> Int (n +  x)
            Str s -> Str (s ++ y)

【讨论】:

    猜你喜欢
    • 2015-12-24
    • 1970-01-01
    • 2017-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多