- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
签名应该是:
tailMay :: Foldable f => f a -> Maybe (f a)
我得到了 headMay
的定义,这是有道理的,并且(对我来说)相当聪明:
headMay :: Foldable f => f a -> Maybe a
headMay = foldr (const . Just) Nothing
不幸的是,我无法想到 tailMay
类似的东西。 ,和similar implementations似乎使用了魔法或不安全的函数。
如果这是不可能的,那么可以使用 (Applicative t, Foldable t)
的方法也适合我的目的(我认为这也意味着 Traversable t
)。
最佳答案
Tail 仅对类似列表的结构有意义,因此返回列表而不是相同的容器类型 f
是明智的。实现很简单,可以通过多种方式完成,这里是一种。
import Control.Monad (guard)
import Data.Foldable (toList)
tailMay :: Foldable f => f a -> Maybe [a]
tailMay xs = guard (not (null xs)) >> Just (drop 1 (toList xs))
但是,由于它适用于所有类似列表的结构,因此我们可以很酷地为所有具有 IsList 的事物定义它。
{-# LANGUAGE TypeFamilies #-}
import Control.Monad (guard)
import Data.Foldable (toList)
import GHC.Exts (IsList(Item, fromList))
tailMay :: (IsList l, Item l ~ a, Foldable f) => f a -> Maybe l
tailMay xs = guard (not (null xs)) >> Just (fromList (drop 1 (toList xs)))
编辑
上述解决方案的一个好处是您可以将类型从参数更改为结果。例如,您可以从 Vector
开始,然后使用 Set
结果。但这也有一个缺点,您需要自己指定结果类型:
因此运行此命令将导致编译错误:
λ> tailMay [1 :: Int]
<interactive>:24:1-18: error:
• Illegal equational constraint Item l ~ Int
(Use GADTs or TypeFamilies to permit this)
• When checking the inferred type
it :: forall l. (IsList l, Item l ~ Int) => Maybe l
λ> tailMay [1 :: Int] :: Maybe [Int]
Just []
如果上述确实是一个问题或者对我们来说只是一个不希望的效果,我们可以轻松限制结果类型:
tailMay :: (IsList l, Item l ~ a, Foldable f, l ~ f a) => f a -> Maybe l
之后效果很好:
λ> import qualified Data.Vector as V
λ> tailMay $ V.enumFromTo 'a' 'd'
Just "bcd"
λ> tailMay [1 :: Int]
Just []
λ> tailMay V.empty
Nothing
λ> tailMay []
Nothing
警告 - 一切都会很棒,但不幸的是,不能保证 fromList
将有一个完整的实现:
λ> import qualified Data.List.NonEmpty as NE
λ> tailMay (5 NE.:| [] :: NE.NonEmpty Int)
Just *** Exception: NonEmpty.fromList: empty list
除了创建您自己的 IsList
之类的类并为所有此类数据结构提供您自己的实例之外,没有通用的方法可以保护您自己免受其影响。
关于haskell - 如何在 Haskell 中为 Foldable 编写 tailMay,而不使用不安全的函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58977458/
签名应该是: tailMay :: Foldable f => f a -> Maybe (f a) 我得到了 headMay 的定义,这是有道理的,并且(对我来说)相当聪明: headMay ::
我是一名优秀的程序员,十分优秀!