(Haskell)将函数类型转换为可能

时间:2016-06-04 17:44:39

标签: haskell maybe

给出一个函数:(a - > a)我们应该使用该函数并将其类型转换为(也许a - >可能是a)。我有点坐在这里尝试一切可能,但我只得到类型可能(a - > a),但我不知道改变实际的输入和输出。所以有人可以给我一些解决这个问题的提示或想法,所以我可以自己尝试一下吗?感谢。

2 个答案:

答案 0 :(得分:5)

假设你有

f :: a -> a

你需要构建

g :: Maybe a -> Maybe a
g = ...

我们如何构建它?首先,它是一个参数的函数,所以它应该是这样的:

g = \x -> ...

其次,我们有Maybe类型的参数,因此我们可以分别分析两个案例:

g = \x -> case x of
  Nothing -> ... (1)
  Just y -> ... (2)

在(1)中,我们做不了多少:我们无法生成抽象类型a的值,因此无法使用Just。我们唯一可以使用的是Nothing

在(2)中,我们有三个选择:

a)再次Nothing,所以我们得到一个无聊的解决方案:

g = \x -> case x of
  Nothing -> Nothing
  Just y -> Nothing

只是

g = \x -> Nothing

b)或者,我们有y::a,因此我们可以返回Just y

g = \x -> case x of
  Nothing -> Nothing
  Just y -> Just y

只是

g = \x -> x -- = id

c)或者,我们可以将f应用于y,以获得a类型的新值。我们需要做的就是将这个值包装在Just

g = \x -> case x of
  Nothing -> Nothing
  Just y -> Just (f y)

正如@chi指出的那样,我们可以继续将f应用于结果,因此我们也可以针对任意数量的Just (f (f ... (f y)...))返回f

只有(c)使用f,所以这是唯一的非平凡解决方案。

为了完整起见,值得注意的是,对于真实世界的应用,(b)和(c)都是等价的,因为f除了id之外什么都不是f

正如@amalloy指出的那样,如果我们将id作为参数而不是全局函数,则不是这种情况,因为只有a->a可以作为a用于任何a->a但是,对于给定的a ,有许多类型为g 的函数。所以,如果你的g :: (a->a)->(Maybe a->Maybe a) 应该是

Maybe

然后(b)和(c)不再相同。

当然,这可以通过多种方式编写:上面的幼稚版本,使用事件Monadfmap,使用来自Functor Maybe的{​​{1}}(信用到@amalloy),但结果将是相同的。

答案 1 :(得分:1)

要避免最终的答案真的很难,因为这是一个微不足道的问题,真的。

检查标准函数fmap的签名(我将删除约束部分,因为我们现在不需要它):

fmap :: (a -> b) -> f a -> f b

您可以将其视为两个参数(a -> b)f a的函数,生成结果f b。但是,以下签名完全相同:

fmap :: (a -> b) -> (f a -> f b)

钟声响起吗?是的,fmap也可以看作是一个参数(a -> b)的函数,从而产生(f a -> f b)函数。

现在,这些签名中的f代表具有Functor实例的任何类型,其中Maybe就是这种情况。现在,弄清楚其余部分:)