41

language プラグマがすべての文字列リテラルOverloadedStringsを暗黙的にラップしていることは承知しています。fromString私がやりたいのは、実際に文字列をオーバーロードすることではなく、常にに変換されるように意味を変更することTextです。したがって、文字列リテラルを文字のリストとして使用すると、型エラーが発生するはずです。

そのクラスのインスタンスIsStringもインポートせずにクラスをインポートすることは不可能のようです。Stringghc は、文字列リテラルをTextのみに制限する方法を提供していますか?

4

2 に答える 2

47

少しやり過ぎですが、1 つの解決策は と を組み合わせることOverloadedStringsですRebindableSyntax。このRebindableSyntax拡張により、Haskell 構文がスコープ内にある関数を参照するために使用するすべての暗黙的な関数呼び出しが発生します。たとえば、整数リテラルは any を使用しますがfromIntegral、必ずしも ではありませんPrelude.fromIntegral。副作用として、Preludeは暗黙的にインポートされなくなったため、手動で行う必要があります。インポートする限り、間違った関数を暗黙的に使用する構文に問題はないはずです (私は、実際にこの手法を使用したことはないと思います)。と組み合わせるとOverloadedStrings、必ずしも ではなく、スコープ内にあるものはすべて"foo"に変換されます。だから同義にするfromString "foo"fromStringData.String.fromString "foo"fromStringpackあなたが望むことをします。完全な例:

{-# LANGUAGE OverloadedStrings, RebindableSyntax #-}
import Prelude

import qualified Data.Text    as T
import qualified Data.Text.IO as T

fromString :: String -> T.Text
fromString = T.pack

main :: IO ()
main = T.putStrLn "Hello, world!"

これは正常に機能し、に変更mainするとmain = putStrLn "Hello, world!"、目的のエラーが発生します。

TestStrings.hs:11:17:
    Couldn't match expected type `String' with actual type `T.Text'
    Expected type: [Char] -> String
      Actual type: String -> T.Text
    In the first argument of `putStrLn', namely `"Hello, world!"'
    In the expression: putStrLn "Hello, world!"

の定義をコメントアウトするfromStringと、別のエラーが発生します。

TestStrings.hs:11:19:
    Not in scope: `fromString'
    Perhaps you meant `showString' (imported from Prelude)

厳密なテキストと遅延テキストの両方で機能させたい場合は、独自のIsString型クラスを定義して、両方をインスタンスにすることができます。IsStringメソッドがある限り、クラスを呼び出す必要はありませんfromString

また、警告の言葉: GHC マニュアルの のセクションでは関数RebindableSyntaxについて言及されておらず、 のセクションでは について言及されていません。これが機能しない理由はありませんが、これは、このソリューションが技術的に文書化されていない動作に依存していることを意味すると思います。fromStringOverloadedStringsRebindableSyntax

于 2012-07-19T02:42:10.807 に答える