【问题标题】:Pattern matching with Alternative empty or Applicative pure与 Alternative empty 或 Applicative pure 的模式匹配
【发布时间】:2020-02-19 15:19:46
【问题描述】:

我知道可以像这样对(命名的)构造函数进行模式匹配:

f1 :: Maybe a -> Bool
f1 Nothing = False
f1 (Just x) = True -- in reality have something that uses x here

f2 :: [a] -> Int
f2 [] = False
f2 x = True

如何为一般Alternatives写这样的函数类似于

f :: (Alternative m) => m a -> Bool
f empty = False
f x = True

如果我尝试这个,我会收到错误 Parse error in pattern: empty。我想这是有道理的,因为empty 在这里是一个函数而不是构造函数。但是对于一般的Alternatives,我怎样才能做到这一点呢?

编辑 1: 我的实际目标是为自定义结果类型定义一个Monad 实例(也可能还有一个MonadPlus 实例)。代替基本的Either Error Result 类型,它应该支持Maybe Error(如果可能还支持其他Alternatives,如[Error])作为错误类型,还应该支持一些Applicative 作为结果类型,以支持惰性求值,例如标记器的结果类型(Maybe Error, [Tokens])

我想要类似的东西

instance (Alterantive mErr, Applicative mRes) => Monad (mErr e, mRes a) where
  return x = (empty, pure x)
  (empty, pure x) >>= f = f x
  (err, x) >>= f = (err, x)

【问题讨论】:

  • empty 不是函数;这是一个价值。但它是一个值的name,而不是创建该值的构造函数。
  • @chepner 出于好奇,值和函数之间有什么区别吗? Haskell 的类型系统似乎没有任何作用。至少这是我的新手对它的看法。
  • 嗯,所有函数都是值,但并非所有值都是函数。函数具有由(->) 运算符创建的类型,而f a 不一定是这样的类型。

标签: haskell typeclass alternative-functor


【解决方案1】:

你能做的最好的就是:

f :: (Eq (m a), Alternative m) => m a -> Bool
f x | x == empty = False
    | otherwise = True

【讨论】:

    【解决方案2】:

    实际上可以使用-XPatternSynonyms-XViewPatterns

    {-# LANGUAGE PatternSynonyms #-}
    {-# LANGUAGE ViewPatterns #-}
    import Control.Applicative (empty)
    
    pattern Empty :: (Eq (m a), Alternative m) => m a
    pattern Empty <- ((==) empty -> True)
    
    f :: (Eq (m a), Alternative m) => m a -> Bool
    f Empty = False
    f _ = True
    

    【讨论】:

    • 这不是你想要的。这里,empty 是一个未绑定的变量(就好像你写了pattern Empty &lt;- x,并且模式总是匹配的,所以f [1,2,3] 返回False
    • 啊,我的错。答案已调整。
    • 再一次,还是不行。如果你想做@mithrandi 正在做的事情,pattern Empty &lt;- ((empty ==) -&gt; True)。你需要那个Eq
    【解决方案3】:

    Eq 约束中滑动,就像在mithrandi's answer 中一样,确实是可以做到的最好的。无论如何,值得强调的是它是有代价的:我们现在被困在一个 Eq 常量上,如果我们仅仅针对 []Nothing 进行模式匹配,这将是不必要的。避免此问题的常用方法是使用null :: Foldable t =&gt; t a -&gt; Bool。但是,在这里,该选项也不是很好,因为FoldableAlternative 基本上无关,并且与您的用例完全不同。特别是,不能保证在一般情况下,null 只存在一个值,这意味着它可能适用于不是相关 Alternative 实例的 empty 的值.

    最终,完全符合要求的唯一工具很可能是带有isEmpty 方法的Alternative 子类。我认为这在任何地方都不存在,而且在召唤这样的东西时,功率重量比似乎并不令人鼓舞。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多