6

ユーザーにダイアログを表示する方法を構築しています。

data DialogConfig t m b e =
  DialogConfig { _dialogConfig_title :: Dynamic t T.Text
               , _dialogConfig_content :: b -> m (Dynamic t (Maybe b))
               , _dialogConfig_footer :: Dynamic t (Maybe b) -> m (Event t e)
               }
dialog :: MonadWidget t m =>
           DialogConfig t m b e -> Event t b -> m (Event t (DialogEvent e))

関数の初期化にある種の「デフォルト」インスタンスを使用して、たとえばとして使用できるようにしたいとDialogConfig思います。しかし、私は型推論と戦っています。これは機能します:dialogdefaultConfig{_dialogConfig_content=content}

confirmDialog :: forall t m. MonadWidget t m =>
                 T.Text -> Event t T.Text -> m (Event t ())
...
evt <- dialog
         (DialogConfig { _dialogConfig_title = constDyn title
                       , _dialogConfig_content = content
                       , _dialogConfig_footer = buttons}
                       ) contentEvt

ただし、デフォルトを使用するとDialogConfig(たとえば、ここでは直接インライン化されます)、次のことはできません。

evt <- dialog
      (DialogConfig { _dialogConfig_title = constDyn mempty
                    , _dialogConfig_content = const $ return $ constDyn Nothing
                    , _dialogConfig_footer = const $ return never }
                    { _dialogConfig_title = constDyn title
                    , _dialogConfig_content = content
                    , _dialogConfig_footer = buttons}
                    ) contentEvt

エラーは次のとおりです。

Could not deduce (Reflex t0) arising from a use of ‘constDyn’ from the context (MonadWidget t m)
Could not deduce (Monad t1) arising from a use of ‘return’ from the context (MonadWidget t m)

asScopedTypeVariablesでデフォルトの設定を使用して入力することはできますが、それがなくても動作するはずではありませんか? タイプはかなり明確であるように私には思えます。confirmDialogDialogConfig t m a b

4

1 に答える 1

4

コメントで述べたように、問題は、レコードの更新によってレコードのタイプが変更される可能性があることです (最初は驚くかもしれません)。GHCi でのテストは次のとおりです。

> data T a = T { tA :: a }
> let x = T "foo"
> :t x
x :: T [Char]
> :t x { tA = True }
x { tA = True } :: T Bool

したがって、デフォルトを定義することはできません。

> let def :: Read a => T a ; def = T (read "True")
> :t def :: T Bool
def :: T Bool :: T Bool
> :t def { tA = 5 }
   Could not deduce (Read t0) arising from a use of ‘def’
   The type variable ‘t0’ is ambiguous

実際、上記defは任意のタイプである可能性があります。

T a -> T a考えられる解決策は、継続関数を要求することによって更新を強制的に同じ型にすることです。

> let defF :: Read a => (T a -> T a) -> T a ; defF f = f (T (read "True"))
> :t defF (\d -> d { tA = False })
defF (\d -> d { tA = False }) :: T Bool

上記dはデフォルトであり、構造上、更新後に同じタイプのレコードを持つ必要があります。

レンズの場合、より良いアプローチがあるかもしれません。

于 2016-04-27T09:02:04.923 に答える