关于Maybe

时间:2017-09-08 06:42:45

标签: haskell

我正在研究Blow Your Mind

中的Haskell习语
-- split at whitespace
-- "hello world" -> ["hello","world"]

unfoldr (\b -> fmap (const . (second $ drop 1) . break (==' ') $ b) . listToMaybe $ b)

据我所知,展开者应该是:

unfoldr :: (b -> Maybe (a,b)) -> b -> [a]
unfoldr f b = 
case f b of
  Just (a, new_b) -> a : unfoldr f new_b
  Nothing         -> []

所以f b必须在最后输出Nothing,对吧?

所以我试着理解f部分fmap (const . (second $ drop 1) . break (==' ') $ b) . listToMaybe $ b)

我明白了第二个,下降,休息,listToMaybe。但我无法弄清楚为什么组合这样的函数可以输出Nothing。

Const始终忽略第二个参数。那么为什么fmap (const . (second $ drop1) . break (==' ') $ b) . listToMaybe $ b最终会输出Nothing?

2 个答案:

答案 0 :(得分:3)

(const . (second $ drop 1) . break (==' '))的类型为[Char] -> b -> ([Char], [Char])

这个复杂的函数只需要一个字符串(例如"one two three")和任何参数,然后返回("one", "two three")

因此,(const . (second $ drop 1) . break (==' ')) $ "one two three"接受任何参数并返回("one", "two three")

fmap (const . (second $ drop 1) . break (==' ') $ b) . listToMaybe $ b

相同

fmap (const . (second $ drop 1) . break (==' ') $ b) $ listToMaybe b

e.g。该函数为fmappedMaybe值,但fmap实例的Maybe定义为:

instance  Functor Maybe  where
    fmap _ Nothing       = Nothing
    fmap f (Just a)      = Just (f a)

这意味着如果fmap中的Nothinga,则fmap f a会返回Nothing

listToMaybe会返回Just列表的第一个元素,如果列表为空则返回Nothing。这就是为什么

fmap (const . (second $ drop 1) . break (==' ') $ b) $ listToMaybe b

Nothing为空列表时,

将返回b

答案 1 :(得分:2)

代码以令人困惑的方式编写。 fmap (const xyz)基本上滥用Maybe a作为布尔切换:如果是Just _ᴡʜᴀᴛᴇᴠᴇʀ,则结果为Just xyz,而简单地传递Nothing。如果列表为空,这样的任何内容都不会直接来自listToMaybe,这就是这个组合可以产生Nothing的方式。

写这一切的首选方式是

unfoldr (\b -> listToMaybe b *> Just (second (drop 1) (break (==' ') b)))

或确实使用旧的旧do符号

unfoldr $ \b -> do
    listToMaybe b
    return . second (drop 1) $ break (==' ') b

但实际上,明确的模式匹配会更加清晰:

{-# LANGUAGE LambdaCase #-}
unfoldr $ \case
   [] -> Nothing
   b -> Just . second (drop 1) $ break (==' ') b