1

私はこのようなサンプルタイプを持っています:

data Sample_Type = Sample_Type { field1 :: Int,
                                 field2 :: Int,
                                 field3 :: [Int]
                               } deriving (Show, Eq)

この関数を使用してfield3、レコード内にリストを追加しています。

insertPlan :: [Sample_Type] -> Sample_Type -> Int -> [Sample_Type]
insertPlan [] _ _ = []
insertPlan (x:xs) y b = if (x == y)
                        then (y {field3 = b:(field3 y)}):xs
                        else x:(insertPlan xs y b)

上記の関数をより一般的な形式に変換しようとしています (更新が必要なリストが 1 つある多くのレコード データ型があるため)。

次のコードを思いつきましたが、うまくいきません (明らかに):

insertVariant :: [a] -> a -> (a -> [Int]) -> Int -> [a]
insertVariant (x:xs) a f b  = if (x == a)
                              then (a {f = b:(f a)}):xs
                              else x:(insertVariant xs a b)

この問題を解決する良い方法はありますか?

4

2 に答える 2

1

MultiParamTypeClasses型クラスは 1 つの解決策ですが、拡張機能が必要になります。

{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}

class Insertable i a where
    insertInto :: i -> a -> i


data SampleType = SampleType
    { field1 :: Int
    , field2 :: Int
    , field3 :: [Int]
    } deriving (Show, Eq)

instance Insertable SampleType Int where
    insertInto (SampleType f1 f2 f3) x = SampleType f1 f2 (x:f3)

data MyType = MyType
    { mtField1 :: String
    , mtField2 :: [String]
    } deriving (Show, Eq)

instance Insertable MyType String where
    insertInto (MyType f1 f2) x = MyType f1 (x:f2)

insertPlan :: (Eq i, Insertable i a) => [i] -> i -> a -> [i]
insertPlan [] _ _ = []
insertPlan (x:xs) y b =
    if x == y
        then insertInto y b : xs
        else x : insertPlan xs y b


main = do
    let s = SampleType 1 2 [1..5]
        m = MyType "Testing" ["world"]
    print $ insertPlan [s] s (6 :: Int)
    print $ insertPlan [m] m "Hello"

いくつかの注意事項:

  1. FlexibleInstancesは forの型シノニムであるinstance MyType Stringため、コンパイラはこの拡張子なしでそれを拒否します。String[Char]
  2. の型を指定する必要がありまし6た。そうしないと、コンパイラはどの型6が想定されているかを判断できないためです。
  3. MultiParamTypeClassesなしでこれを書くことはできますinsertIntoが、リストに挿入されているものに対して型チェックを行うことができませんでした。ただし、他の解決策があります。
于 2013-10-06T00:26:02.533 に答える