首页 > 解决方案 > 如何在 Protolude 中访问文本分解功能

问题描述

TL;博士:

在标准前奏中,可以使用String诸如等功能head对文本进行操作takeProtolude用更好的组件替换这些组件,但这似乎是以失去将许多前奏的功能应用于其标准的能力为代价的文本类型。

一个简单的问题

我需要找出某个单词是否以大写字符开头。

热身

import Data.Char

startsWithUppercase :: String -> Bool
startsWithUppercase = isUpper . head

这行得通...

λ startsWithUppercase "Yes"
True
λ startsWithUppercase "no"
False

除了那head是一个偏函数

λ startsWithUppercase ""
*** Exception: Prelude.head: empty list

更安全的版本

import Data.Char
import Data.Maybe

safeHead :: [a] -> Maybe a
safeHead []    = Nothing
safeHead (x:_) = Just x

startsWithUppercase :: String -> Bool
startsWithUppercase = (maybe False isUpper) . safeHead

这似乎可以解决问题:

λ map startsWithUppercase $ words "Yes no"
[True,False]
λ startsWithUppercase ""
False

除了我想使用Text而不是String

从 移动StringText

让我们尝试直接翻译:

{-# LANGUAGE OverloadedStrings #-}

import Prelude hiding (head)
import Data.Text
import Data.Char
import Data.Maybe

safeHead :: Text -> Maybe Char
safeHead "" = Nothing
safeHead t  = Just . head $ t

startsWithUppercase :: Text -> Bool
startsWithUppercase = (maybe False isUpper) . safeHead

它似乎工作......

yes, no, crash :: Text
yes   = "Yes"
no    = "no"
crash = ""

λ Prelude.map startsWithUppercase [yes, no, crash]
[True,False,False]

...但我不禁想知道为什么 Hoogle 没有提出任何有趣的回应Text -> Maybe Char

无论如何,我厌倦了到处都是这些部分功能:我不希望我的静态保证中有这些巨大的漏洞。我知道,让我们使用这些现代 Prelude 替代品之一。Protolude 看起来不错,而且似乎有很多支持者。

移动到 Protolude

Protolude,在它的众多优点中,应该解决我上面提到的两个主要问题:

它甚至为我进口Data.Maybe

听起来很棒。我们开始做吧!

无需编写safeHead,因为 inProtolude head已经是安全的,并且可以通用:

λ :t head
head :: Foldable f => f a -> Maybe a

出色的!

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE NoImplicitPrelude #-}

import Protolude
import Data.Char

startsWithUppercase :: Text -> Bool
startsWithUppercase = (maybe False isUpper) . head

哦亲爱的:

 Lib.hs     8  23 error           [-Wdeferred-type-errors]
     • Couldn't match type ‘Text’ with ‘f0 Char’
       Expected type: Text -> Bool
         Actual type: f0 Char -> Bool
     • In the expression: (maybe False isUpper) . head
       In an equation for ‘startsWithUppercase’:
           startsWithUppercase = (maybe False isUpper) . head (intero)

Protolude.headFoldable是在s上定义的,但Text不是。

我想我最终还是得自己safeHeadText

嗯,但为此我使用Text.headProtolude隐藏了它。

在无数次尝试让这个工作失败之后,我不得不退后一步思考:我正在尝试找出Text一段现代前奏曲中的第一个字符是否是大写的。

我错过了什么?这个简单问题的合理解决方案是什么?更一般地说,一个人如何分解成内部Text的子文本? Protolude

编辑:澄清

我想从中获得的好处Protolude包括

Protoludetext作为一个依赖,它进口Text组件。

我正在寻找一种实现 whis 的方法,而无需显式指定导入和依赖项,而Protolude.

具体来说,导出的 , 等是head在和上定义的,不能与 一起使用。任何从显式(不受欢迎的样板编号 1)导入任何内容的尝试都会失败,因为它是“隐藏包的成员”。要解决这个问题,必须明确指定为依赖项(不受欢迎的样板编号 2)。takeanyProtolude[]FoldableTextData.Texttexttext

有没有办法让它在没有显式导入和/或依赖项的情况下工作?

标签: haskell

解决方案


怎么样any isUpper . take 1(使用 和 的适当Data.Text变体anytake


推荐阅读