3

sinまたはsinをラップしないことを除いて、と同じように動作するshow(それを呼びましょう)のバリアントが欲しいのですが。例:labelshowString" "Char' '

> label 5
"5"
> label "hello"
"hello"
> label 'c'
"c"

これを手動で実装しようとしましたが、いくつかの壁にぶつかりました。これが私が試したことです:

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
module Label where

class (Show a) => Label a where
    label :: a -> String

instance Label [Char] where
    label str = str

instance Label Char where
    label c = [c]

-- Default case
instance Show a => Label a where
    label x = show x

ただし、デフォルトのケースのクラスはと重複instance Label [Char]しているためinstance Label Char、これらの型は関数では機能しませんlabel

この機能を提供するライブラリ関数はありますか?そうでない場合、上記のコードを機能させるための回避策はありますか?

4

4 に答える 4

5

インスタンスは「ヘッド」 、つまりクラス名の後の部分のみに基づいて選択されるため、上記のコードは機能しません。「コンテキスト」、=>「Show a」などの前のものは、後でのみ調べられます。コンテキストはインスタンスを削除してコンパイラエラーを生成できますが、コンパイラが別のインスタンスを選択することはありません。この動作のため、重複するインスタンスは潜在的なあいまいさです。

より複雑なインスタンスを作成できるコンパイラ拡張機能がありますが、Labelクラスの個々のインスタンスを作成するのがおそらく最善だと思います。このためにどのような目的を考えていますか?達成しようとしていることによっては、すでにそこにもっと特別な目的があるかもしれません。

ただし、サンプルコードは非常に単純です。必要に応じて、OverlappingInstances拡張機能を追加するだけで、それ以上変更することなく機能するはずです。使用するOverlappingInstancesと、明らかな「最も具体的な」インスタンスがある限り、GHCはある程度のあいまいさを許容します。コードでは、具象型の2つのインスタンスは可能な限り具体的であるため、問題はありません。

読みやすくするために、作業中に追加することTypeSynonymInstancesもできます。

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverlappingInstances #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE TypeSynonymInstances #-}
module Label where

class (Show a) => Label a where
    label :: a -> String

instance Label String where label x = x

instance Label Char where label x = [x]

instance (Show a) => Label a where label = show
于 2010-06-04T02:37:58.713 に答える
1

OverlappingInstancesこれを機能させる言語拡張機能があります。

于 2010-06-04T02:41:09.697 に答える
1

この機能を提供するライブラリ関数はありますか?

はい。toSと同様に使用できる、などの便利な機能を提供するかなり新しいライブラリがありますshow。(ドキュメントを参照

次のように、string-convパッケージの下にcabalをインストールできます。cabal install string-conv

参照: ハッキング

于 2015-06-19T19:54:30.960 に答える
0

タイプ(Typeable)に余分な制約が追加されるため、実際には必要なものではありませんが、これは一般的にそれを行う方法です。

Data.Generics>(show `extQ`(id :: String-> String)` extQ`((:[]):: Char-> String))1

「1」

Data.Generics>(show `extQ`(id :: String-> String)` extQ`((:[]):: Char-> String)) "hello"

"こんにちは"

Data.Generics>(show `extQ`(id :: String-> String)` extQ`((:[]):: Char-> String))'c'

「c」

Data.Generics>(show `extQ`(id :: String-> String)` extQ`((:[]):: Char-> String))['f'、'l']

「fl」

Data.Generics>:t(show `extQ`(id :: String-> String)` extQ`((:[]):: Char-> String))

(show `extQ`(id :: String-> String)` extQ`((:[]):: Char-> String))::(Show a、Typeable a)=> a-> String

于 2010-06-08T11:07:54.777 に答える