3

Traversal として文字列リテラルを使用したいのですが、型が少しわかりません。このインスタンスを作成することは可能ですか?

import Control.Lens
import Data.Aeson
import Data.Aeson.Lens
import Data.String
import Data.Default

{- Having:
key'  :: AsValue t => Text -> Traversal' t (Maybe Value)
_JSON :: (ToJSON a, FromJSON a) => Traversal' t a
-}

instance (AsValue t, FromJSON v, ToJSON v, Default v) => IsString (Traversal' t v) where
  fromString k = key' (fromString k) . non (toJSON def) . _JSON

State モナド内でこのようなことを達成するには:

"some-key" .= (3 :: Int)

全称量化型インスタンスの問題。ありがとう!

4

1 に答える 1

5

あなたのコードをコンパイルできませんでしたが、それは問題ではありません。タイプの関数があると仮定します

fromStringTraversal :: (AsValue t, FromJSON v, ToJSON v, Default v) 
                    => String -> Traversal' t v 
fromStringTraversal = undefined

次に、インスタンスを記述するTraversal'には、インスタンス ヘッドに の定義をインライン化するだけです。これが機能するのは、インスタンス内のすべての型変数が暗黙のうちに普遍的に量化されるためです。

{-# LANGUAGE RankNTypes, FlexibleInstances, GADTs #-}

instance (a ~ a', b ~ b', AsValue b, Default a, FromJSON a, ToJSON a, Applicative f) 
       => IsString ((a -> f a') -> b -> f b') where
  fromString = fromStringTraversal

a ~ a', b ~ b'制約をコンテキストからインスタンス ヘッドに移動することもできますが、この方法により、より適切な型推論が得られます。それで

{-# LANGUAGE OverloadedStrings, NoMonomorphismRestriction #-}

-- Infered type:
-- test :: (AsValue s, MonadState s m) => m ()
test = "some-key" .= (3 :: Int)
于 2015-02-13T22:45:50.890 に答える