简体   繁体   English

Haskell函数组成可能

[英]Haskell function composition on Maybe

I was studying Haskell idioms from Blow Your Mind 我在研究《 吹牛》中的 Haskell成语

-- split at whitespace
-- "hello world" -> ["hello","world"]

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

From what I know, unfoldr is supposed to be: 据我所知,文件夹应该是:

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

So fb must output Nothing at the end, right? 所以fb必须在末尾什么都不输出,对吗?

So I tried to understand the f part, fmap (const . (second $ drop 1) . break (==' ') $ b) . listToMaybe $ b) 所以我试图理解f部分fmap (const . (second $ drop 1) . break (==' ') $ b) . listToMaybe $ b) fmap (const . (second $ drop 1) . break (==' ') $ b) . listToMaybe $ b) . fmap (const . (second $ drop 1) . break (==' ') $ b) . listToMaybe $ b)

I get the idea of second, drop, break, listToMaybe. 我有第二个想法,drop,break,listToMaybe。 But I can't figure out why composing functions like this can output Nothing. 但是我不知道为什么这样的组合函数不能输出Nothing。

Const always ignore the second parameter. Const始终忽略第二个参数。 So why fmap (const . (second $ drop1) . break (==' ') $ b) . listToMaybe $ b 那么为什么要使用fmap (const . (second $ drop1) . break (==' ') $ b) . listToMaybe $ b fmap (const . (second $ drop1) . break (==' ') $ b) . listToMaybe $ b can output Nothing in the end? fmap (const . (second $ drop1) . break (==' ') $ b) . listToMaybe $ b到底可以输出什么?

The type of (const . (second $ drop 1) . break (==' ')) is [Char] -> b -> ([Char], [Char]) (const . (second $ drop 1) . break (==' '))[Char] -> b -> ([Char], [Char])

This sophisticated function just takes a string (for example "one two three" ) and any argument and returns ("one", "two three") . 这个复杂的函数只需要一个字符串(例如"one two three" )和任何参数并返回("one", "two three")

Therefore, (const . (second $ drop 1) . break (==' ')) $ "one two three" takes any argument and returns ("one", "two three") . 因此, (const . (second $ drop 1) . break (==' ')) $ "one two three"采用任何参数并返回("one", "two three")

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

is the same as 是相同的

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

eg the function is fmapped to a Maybe value, but the definition of fmap for Maybe instance is: 例如,将函数fmappedMaybe值,但是Maybe实例的fmap定义为:

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

which means that fmap returns Nothing if a in fmap fa is Nothing . 这意味着fmap返回Nothing如果afmap faNothing

listToMaybe returns Just first element of a list, or Nothing if the list is empty. listToMaybe返回Just一个列表的第一个元素,或者Nothing ,如果该列表是空的。 That's why 这就是为什么

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

will return Nothing , when b is an empty list. b为空列表时,将返回Nothing

The code is written in a confusing manner. 代码以混乱的方式编写。 fmap (const xyz) basically abuses Maybe a as a bool switch: if it's Just _ᴡʜᴀᴛᴇᴠᴇʀ , the result will be Just xyz , while a Nothing is simply passed on. fmap (const xyz)基本上将Maybe a当作bool开关来滥用:如果它是Just _ᴡʜᴀᴛᴇᴠᴇʀ ,结果将是Just xyz ,而Nothing只是简单地传递了。 Such a nothing can come straight from listToMaybe in case of an empty list, that's how this composition can yield Nothing . 在列表为空的情况下, listToMaybe可能Nothing ,这就是这种组合不能产生Nothing

The preferred style of writing all this would be 所有这些的首选写作风格是

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

or indeed with good old old do notation 或者实际上具有良好的老旧do记号

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

But really, an explicit pattern match would be much clearer: 但实际上,显式模式匹配会更加清晰:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM