1. ホーム
  2. haskell

多変量解析のhaskell関数を作成する方法とは?

2023-10-19 22:45:16

質問

私は任意の数の引数(すべて同じ型)を取り、それらを使って何かを行い、その後結果を返す関数が必要です。引数のリストは、私の特定のケースでは実用的ではありません。

私はhaskellのライブラリに目を通したとき、私は関数 printf (モジュールから Text.Printf ) も同じようなトリックを使っています。残念ながら、ソースを見ただけでは、そのマジックは理解できませんでした。

誰かこれを達成する方法を説明してくれませんか、または少なくとも、これに関する良い説明を見つけることができるいくつかの Web ページ/紙/何でも?

動機は?

私がこれを必要とする理由は、実に単純です。学校(コンピュータサイエンスクラス)では、数式を記録し、それを文字列として表現し(独自のデータ型のためにNum/Realなどのインスタンスを書くことによって)、それに対してさまざまな操作を実行できるモジュールを書くことが要求されます。

このデータ型は変数のための特別なコンストラクタを含んでおり、指定された関数によって値や何かに置き換えることができる。目標のひとつは、このような式をいくつかの変数(型のペア)と共に受け取る関数を書くことです。 (Char,Rational) のペア)を受け取り,式の結果を計算する関数を書くことである.この関数の目標をどのように表現したらよいかを考えてみよう。(私の考え この関数は、関数内で定義されたvarsと正確に同じ数の引数を取る別の関数を返します - 不可能のようです)。

どのように解決するのか?

のキーポイントは printf は、文字列か関数のどちらかを返すことができることです。コピー元は http://www.haskell.org/ghc/docs/6.12.2/html/libraries/base-4.2.0.1/src/Text-Printf.html ,

printf :: (PrintfType r) => String -> r
printf fmts = spr fmts []

class PrintfType t where
    spr :: String -> [UPrintf] -> t

instance (IsChar c) => PrintfType [c] where
    spr fmts args = map fromChar (uprintf fmts (reverse args))

instance (PrintfArg a, PrintfType r) => PrintfType (a -> r) where
    spr fmts args = \a -> spr fmts (toUPrintf a : args)

で、抽出できる基本構造は

variadicFunction :: VariadicReturnClass r => RequiredArgs -> r
variadicFunction reqArgs = variadicImpl reqArgs mempty

class VariadicReturnClass r where
   variadicImpl :: RequiredArgs -> AccumulatingType -> r

instance VariadicReturnClass ActualReturnType where
   variadicImpl reqArgs acc = constructActualResult reqArgs acc

instance (ArgClass a, VariadicReturnClass r) => VariadicReturnClass (a -> r) where
   variadicImpl reqArgs acc = \a -> variadicImpl reqArgs (specialize a `mappend` acc)

例えば

class SumRes r where 
    sumOf :: Integer -> r

instance SumRes Integer where
    sumOf = id

instance (Integral a, SumRes r) => SumRes (a -> r) where
    sumOf x = sumOf . (x +) . toInteger

であれば

*Main> sumOf 1 :: Integer
1
*Main> sumOf 1 4 7 10 :: Integer
22
*Main> sumOf 1 4 7 10 0 0  :: Integer
22
*Main> sumOf 1 4 7 10 2 5 8 22 :: Integer
59