Haskell-一些实现

时间:2018-12-13 22:35:23

标签: haskell

在文章“ Write you a Haskell”(第34页)中,给出了“一些”和“许多”的以下实现:

  

从Alternative类型类定义中自动得出的是   manysome函数。许多采用单个函数参数,并且   重复应用它直到函数失败,然后产生   到那时为止收集的结果。 some函数的行为类似   如果没有至少一个,它将自身失败   匹配。

-- | One or more.
some :: f a -> f [a]
some v = some_v
  where
    many_v = some_v <|> pure []
    some_v = (:) <$> v <*> many_v

-- | Zero or more.
many :: f a -> f [a]
many v = many_v
  where
    many_v = some_v <|> pure []
    some_v = (:) <$> v <*> many_v

一段时间以来,我一直试图了解这种实现方式。

我不明白如何将“许多”和“一些”应用于“列表”或“也许”

我也不确定(:) <$> v <*> many_v

这是如何得出的?

1 个答案:

答案 0 :(得分:0)

ghc/libraries/base/GHC/Base.hs中有一个递归声明:

    ... :: f a -> f [a]
    ...
        many_v = some_v <|> pure []
        some_v = liftA2 (:) v many_v  -- (:) <$> v <*> many_v

自变量v必须是以下类型的实例的值: Alternative(以及ApplicativeFunctor)。 v已被解除,只需应用(<*>)。 该应用程序将产生一个提升的列表。

somemany构成v的构造函数的递归应用程序, 并将构造的值放入列表中。

  • some在构建第一个empty时停止应用程序
  • many继续进行申请

[]Alternative的实例:

instance Alternative [] where
    empty = []
    (<|>) = (++)

some尝试使用列表:

  av = [[2], [2,3], [], [2,3,5]]
  some av                      -- no error, but never stops
  do {v <- some av; return v;} -- no error, but never stops

相比于letter What are Alternative's "some" and "many" useful for?

  import Control.Monad(Functor(..))
  import Control.Applicative
  import Data.Char
  newtype P a = P { runP :: String -> [(a,String)] }
  instance Functor P where
    fmap f (P q) = P (\s -> [ (f y,ys) | (y,ys) <- q s])
  instance Applicative P where
    pure x = P (\s -> [(x,s)])
    P p <*> P q = P (\s -> [(x y, ys) | (x,xs) <- p s, (y,ys) <- q xs])
  letter = P p where
    p (x:xs) | isAlpha x = [(x,xs)]
    p _ = []
  instance Alternative P where
    P p <|> P q = P (\s-> p s ++ q s)
    empty = P (\s-> [])

用法:

  runP (many letter) "ab123"

letter是一个聪明的构造函数, 使用局部变量P使用字段runP构造一个p值。 (访问器的结果)runP是一个函数。 P是实现Alternative的类型,也是构造函数。 P代表解析器。

fmap未在somemany中使用。 <*>导致函数runP的应用, 谁的论点还没有在这里。 基本上somemany会构造一个程序,该程序会从其参数中获取食物。 参数必须是列表。 由于懒惰,递归在第一个构造函数处停止。

  p = some letter -- constructs a program accessed via @runP@
  runP p "a1" -- [("a","1")]
  q = some [2] -- basically also a program
  q -- never stops

递归应用程序不是empty(列表为[]), 因为没有标准可以停止,也就是没有输入。

这些站:

  some [] -- []
  many [] -- [[]]
  some Nothing -- Nothing
  many Nothing -- Just []

somemanyv)的参数有更多要求。

  • v是作为Alternative实例的类型的值。
  • v类型的构造函数的递归应用程序必须以empty终止。
  • v必须包含在使用<*>进行构造时应用的函数,以具有停止条件。

结论: somemany无法应用于列表值, 即使列表实现了Alternative

为什么列表实现Alternative? 我认为是在Monoid顶部添加<|>接口emptyApplicative, 不是因为somemany

  foldr (<|>) [] [[2],[],[3,4]] -- [2,3,4]

somemany似乎仅用于解析器构造 或更一般而言,使用输入的程序的构造 并产生更多的输出,其中一些可以是empty。 那已经很普遍了。 但是Alternative中的位置仅是合理的, 如果大多数Alternative实例对此有合理的用法。 事实并非如此。