Можно ли как-нибудь проверить, что функция p :: IsString s => s -> Bool
лениво оценивает свой ввод?Таким образом, он только потребляет часть своего ввода при определении своего результата.И возможно ли так, чтобы он был совместим как с String
, так и с Data.Text.Lazy
?
Я смотрел на модульное тестирование Q & A для неопределенного, оцененного в ленивом выражении в Haskell , который конкретно не распространяется на IsString
, и я нашел пакет StrictCheck на Hackage, в котором я не совсем уверен, как работает.Это применимо здесь?
Проблема
У меня есть предикат,
p :: IsString s => s -> Bool
и тест Hspec,
{-# LANGUAGE OverloadedStrings #-}
...
import Data.String (fromString)
spec_p :: Spec
spec_p =
describe "p" $
it "is lazy" $ p (fromString x) `shouldBe` y
where
x = "foo" ++ [undefined]
y = True
, который не проходитесли p ("foo" ++ [undefined])
пытается потреблять больше, чем "foo"
.
Это прекрасно работает для моей String
реализации,
import qualified Data.List as L
p :: String -> Bool
p = ("foo" `L.isPrefixOf`)
Но это не так хорошо работает на моем Data.Text.Lazy
реализация,
{-# LANGUAGE OverloadedStrings #-}
import qualified Data.Text.Lazy as T
import Data.Text.Lazy (Text)
p :: Text -> Bool
p = ("foo" `T.isPrefixOf`)
, поскольку fromString
не преобразует ленивый String
в ленивый Text
способом, который сохраняет undefined
без оценки.Я могу проверить, что ленивая версия работает, написав специализированный тест,
pTest :: Bool
pTest = p (T.fromChunks [ "foo", undefined ]) -- True
, но я не могу контролировать, как fromString
кусков.
Попытка решения:
Я пытался написать свою собственную обертку для управления разбивкой на fromString
,
import qualified Data.Text as T
import qualified Data.Text.Lazy as LT
newtype LazyChunkyText = LazyChunkyText LT.Text deriving (Show)
instance IsString LazyChunkyText where
fromString = LazyChunkyText . LT.fromChunks . map (T.pack . return)
Но поскольку fromChunks
занимает [T.Text]
, мне нужно T.pack
.
Значение моего [undefined]
оценивается.