1

makeLenses制約付きのデータ型でテンプレートを使用できますか? できる場合、その方法は? Template Haskellについてすべて読まずに、そうしたいと思います。

GHC には次の例があります。

{-# LANGUAGE TemplateHaskell, FlexibleInstances, UndecidableInstances, NoMonomorphismRestriction #-}
module Main (main) where

import Control.Lens
import Control.Monad.Reader  -- mtl

class Class1 a where
    someThing :: a  -- just some filler

instance (Num a) => Class1 a where
    someThing = 3

data (Class1 a) => Foo a = Foo { _field1 :: a }

makeLenses ''Foo

main :: IO ()
main = putStrLn . show $ runReader (view field1) $ Foo { _field1 = 5 }

これにより、次のコンパイル エラーが発生します。

Could not deduce (Num a1) arising from a use of ‘Foo’
from the context (Profunctor p, Functor f)
  bound by the type signature for
             field1 :: (Profunctor p, Functor f) =>
                       p a (f a1) -> p (Foo a) (f (Foo a1))
  at src/main.hs:58:1-16
Possible fix:
  add (Num a1) to the context of
    the type signature for
      field1 :: (Profunctor p, Functor f) =>
                p a (f a1) -> p (Foo a) (f (Foo a1))
In the second argument of ‘iso’, namely ‘Foo’
In the expression: iso (\ (Foo x_a3NK) -> x_a3NK) Foo
In an equation for ‘field1’:
    field1 = iso (\ (Foo x_a3NK) -> x_a3NK) Foo

だから私はそれが生成したと思います:

field1 :: Lens' (Foo a) a

私も試してみましmakeFieldsmakeClassyが、役に立ちませんでした。

私はこれを回避できることを知っています:

field1 :: (Class1 a) => Lens' (Foo a) a
field1 = lens _field1 (\ foo val -> Foo { _field1 = val })

makeLensesしかし、テンプレート Haskellでそれを行う方法はありますか?

GHC バージョン 7.8.4 とlensバージョン 4.8 を使用しています。

(注: makeLenses について同様の質問があったことは知っていますが、それでも機能させることができませんでした。私は haskell の初心者です。)

4

1 に答える 1

2

問題は、データ型コンテキストがやや壊れた機能であることだと思います。おそらくGADTを使用するつもりです:

{-# Language GADTs #-}

data Foo a where
  Foo :: Class1 a => a -> Foo a

クラス制約を使用してレコード構文を取得する方法がわかりません。

残念ながら、Ørjan Johansenがコメントしたように、存在型のために、レンズを自動的に作成する際にすぐに問題が発生します。しかし、データ型のコンテキストが機能することは決してなかったのに対し、それらを手で書くことができると私は信じています。

于 2015-03-18T23:33:31.987 に答える