私はかなり多形のライブラリを書き込もうとしています。伝えるよりも見せやすい状況に遭遇しました。これは少し次のようになります。
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
import Data.Map (Map)
import qualified Data.Map as Map
class Format f where type Target f
class Format f => Formatter x f where
target :: forall y. Formatable y => Target f -> x -> y
class Formatable y where name :: y -> String
instance Formatable Integer where name = show
instance Formatable Int where name = show
split :: forall x f. (Format f, Formatter x f) => x -> f -> String -> [Either String (Target f)]
split = undefined
display :: forall x f. (Format f, Formatter x f) => f -> String -> x -> String
display f str x = let
chunks = split x f str
built = foldr apply "" chunks
apply (Left s) accum = accum ++ s
apply (Right t) accum = accum ++ name (target t x)
in foldr apply "" chunks
Format
基本的に、sの数を定義する多形sがありますTarget
。Formattable
さまざまなフォーマットオプションに応答する方法を知っているオブジェクトもいくつかあります(ここでは単純に縮小されていますname
)。
これらFormattables
はさまざまな方法で構成されており、さまざまなターゲットに対応できます。sは、基本的にとFormatter
の間のルーターです。ターゲット(特定の形式から)が与えられると、適切なオブジェクトで応答します。Format
Formattable
Formattable
これはすべてかなり抽象的なものです。次に例を示します。
DateFormat
Year
、、、などのターゲットを指定しMonth
ますDay
。MonthType
「2月」などの名前を持つニューFormattable
タイプですInt
- シンプルなものもあります
instance Formattable Int where name = show
DateTime
の型同義語である可能性があります(Int, MonthType, Int)
。
(明らかに、ここでは正しい値をパイプでつなぐなど、多くの機械を切り取っていますが、あなたはその考えを理解しています。)
display
関数はかなり単純です。フォーマッタ、フォーマットを指定する文字列、表示するオブジェクトを受け取り、すべてを文字列にレンダリングします。
まず、文字列をターゲットと文字列に分割します。たとえば、日付フォーマッタは文字列"%Y-%m-%d"
をに分割する場合があります[Right Year, Left "-", Right Month, Left "-", Right Day]
。split
関数はそれを行い、ここで編集されています。
このdisplay
関数は、各ターゲットのsを追跡しFormattable
、文字列を累積するだけです。
または、少なくとも、そうなるはずです。
ただし、タイプチェックに失敗し、次のエラーが発生します。
Reduced.hs:20:16:
Could not deduce (Target f ~ Target f0)
from the context (Format f, Formatter x f)
bound by the type signature for
display :: (Format f, Formatter x f) => f -> String -> x -> String
at Reduced.hs:(19,5)-(24,30)
NB: `Target' is a type function, and may not be injective
Expected type: [Either [Char] (Target f0)]
Actual type: [Either String (Target f)]
In the return type of a call of `split'
In the expression: split x f str
In an equation for `chunks': chunks = split x f str
Failed, modules loaded: none.
そして、私は私の人生のために理由を理解することはできません。私は何が間違っているのですか?