如何使用Protolude

时间:2019-01-10 19:00:48

标签: haskell

TL; DR:

在标准序言中,可以使用诸如Stringhead等功能的文本(take)进行操作。Protolude用更好的组件替换了这些组件,但这似乎是以丧失将许多Prelude功能应用于其标准文本类型的能力为代价的。

一个简单的问题

我需要确定某些单词是否以大写字母开头。

热身

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

String移至Text

让我们尝试直接翻译:

{-# 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 看起来不错,而且似乎有很多支持者。

移动到协议

该方法具有许多优点,应该解决两个主要问题 我上面已解决的问题:

  • 根除String,使Text默认可用。
  • 清除部分功能,默认情况下使安全功能可用。

它甚至为我导入Data.Maybe

听起来不错。开始吧!

因为safeHead中不需要写Protolude 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.head是在Foldable上定义的,而Text不是。

我想我毕竟必须为safeHead写我自己的Text

嗯,但是为此,我使用了Text.headProtolude将其隐藏起来。

在多次尝试失败后,我不得不退后一步思考:我正在尝试确定是否 在现代情况下,Text的第一个字符是大写 序幕。

我想念什么?解决这个简单问题的明智方法是什么?更笼统地说,如何将Text分解为{em> Protolude内的子文本?

编辑:澄清

我想从Protolude获得的好处包括

  • 减少样板进口
  • 减少样板下垂规格

Protoludetext作为代理,并导入Text组件。

我正在寻找一种实现而不必须显式指定导入和依赖项的方法,这些导入和依赖项必须超出Protolude隐含的含义。

具体来说,由head导出的takeanyProtolude等在[]Foldable上定义,并且与Text不兼容。试图从Data.Text显式导入任何内容(不需要的样板编号1)失败,因为它是“隐藏包text的成员”。为了解决这个问题,必须将text明确指定为依赖项(不理想的样板编号2)。

有没有一种方法可以使它在没有显式导入和/或依赖的情况下工作?

2 个答案:

答案 0 :(得分:3)

any isUpper . take 1(带有Data.Textany的适当take变体)怎么样?

答案 1 :(得分:0)

Protolude导出一个解包函数,使您可以再次使用Strings:

curl -X POST \
  http://localhost:8081 \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -H 'content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' \
  -F 'message=2018-12-27 12:52' \
  -F source=RDW \
  -F object_type=Responses