mykelコードをモジュール化してもらえません。私はおそらくオブジェクト指向のパラダイムに詰まっていて、機能的に考えるのに問題がありますが、私は完全に困惑しています。関数定義を複数のファイルに分割することでモジュール性が向上する
conjunction :: TruthType -> TruthType -> TruthType
conjunction (TT_Percent x) (TT_Percent y) = TT_Percent (x*y)
conjunction (TT_Boolean "t") (TT_Boolean "t") = TT_Boolean "t"
conjunction (TT_Boolean "t") (TT_Boolean "f") = TT_Boolean "f"
conjunction (TT_Boolean "f") (TT_Boolean "t") = TT_Boolean "f"
conjunction (TT_Boolean "f") (TT_Boolean "f") = TT_Boolean "f"
disjunction :: TruthType -> TruthType -> TruthType
disjunction (TT_Percent x) (TT_Percent y) = TT_Percent (x + (1-x)*y)
disjunction (TT_Boolean "t") (TT_Boolean "t") = TT_Boolean "t"
disjunction (TT_Boolean "t") (TT_Boolean "f") = TT_Boolean "t"
disjunction (TT_Boolean "f") (TT_Boolean "t") = TT_Boolean "t"
disjunction (TT_Boolean "f") (TT_Boolean "f") = TT_Boolean "f"
これは、コンパイルして実行:
data TruthType = TT_Boolean String
| TT_Percent Double
conjunction :: TruthType -> TruthType -> TruthType
disjunction :: TruthType -> TruthType -> TruthType
通常は、あなたがこのように、右隣同士に、これらの機能を実装します:
私は、データとそれを操作する二つの機能を持っています私がそれを期待するのとまったく同じです。問題は、約20種類のTruthTypesを実装することを計画していることです。これらのセクションの両方が同じファイル内にある場合
-- TT_Percent
conjunction (TT_Percent x) (TT_Percent y) = TT_Percent (x*y)
disjunction (TT_Percent x) (TT_Percent y) = TT_Percent (x + (1-x)*y)
-- TT_Boolean
conjunction (TT_Boolean "t") (TT_Boolean "t") = TT_Boolean "t"
conjunction (TT_Boolean "t") (TT_Boolean "f") = TT_Boolean "f"
conjunction (TT_Boolean "f") (TT_Boolean "t") = TT_Boolean "f"
conjunction (TT_Boolean "f") (TT_Boolean "f") = TT_Boolean "f"
disjunction (TT_Boolean "t") (TT_Boolean "t") = TT_Boolean "t"
disjunction (TT_Boolean "t") (TT_Boolean "f") = TT_Boolean "t"
disjunction (TT_Boolean "f") (TT_Boolean "t") = TT_Boolean "t"
disjunction (TT_Boolean "f") (TT_Boolean "f") = TT_Boolean "f"
が、私はコンパイルエラーが、私は接続詞を再定義していますことを主張し得る:だから、それは彼らがに作用しているTruthTypeコンストラクタに基づいて、グループに私の機能をより理にかなっています分離関数。私は古い定義を消去したくないので、両方の定義を有効にします。この再定義を許可するために使用できるコンパイラフラグはありますか?
最終的に私の目標は、これらの異なるTruthTypeをそれぞれ独自のファイルに定義することです。私がそれをすると、使用する関数が分からないのであいまいなエラーが出ます。実際に呼び出されているTruthTypeで定義されるのは1つだけなので、GHCにそれらのすべてを試す方法はありますか?
PS。これは型クラスの大きなユースケースのように思えるかもしれませんが、実際はそうではありません。
class (Show a, Eq a) => TruthClass a where
conjunction :: a -> a -> a
disjunction :: a -> a -> a
instance TruthClass Bool where
conjunction True True = True
conjunction True False = False
conjunction False True = False
conjunction False False = False
disjunction True True = True
disjunction True False = True
disjunction False True = True
disjunction False False = False
instance TruthClass Double where
conjunction x y = x*y
disjunction x y = x + (1-x)*y
classReturn :: (TruthClass a) => String -> a -- This fails to compile because it would allow the failure function below, which violates conjunction's type
classReturn "True" = True
classReturn "False" = False
classReturn "1" = 1
classReturn "0" = 0
failure = conjunction (classReturn "True") (classReturn "1")
が
編集:
さて、私は今よりよく説明することができ、私は、「インスタンス」TruthTypeの、この例では「classReturn」機能のようなものを返す関数を書くことができるようにする必要がありますどうして私は型クラスを動作させることができなかったのですか?また、提供されたソリューションがなぜ私にとってうまくいかないのですか? (以下augustssのソリューションに基づいて)次を見てください:
*Main> conjunction True True -- works because type is inferred
True
*Main> classReturn "True" :: Bool -- works because type is explicitly stated
True
*Main> classReturn "True" -- does not work, but this is what I need
<interactive>:1:0:
Ambiguous type variable `a' in the constraint:
`TruthClass a'
arising from a use of `classReturn' at <interactive>:1:0-17
Probable fix: add a type signature that fixes these type variable(s)
私のプログラムでは、私はそれがどのタイプを指定することはできません。私はparsecを使って入力ファイルを解析しています。行 "#bool"にヒットすると、その後に生成されるすべての変数はTT_Boolean型でなければなりません。それが "#percent"になると、後続の変数はすべてTT_Percent型でなければなりません。したがって、私は関数を呼び出すときに型がどのようになるかを厳密に記述することはできません。型クラスを使用する場合は、ハードコードする必要があるようです。データを使用するソリューションはこの問題を解決しますが、データに起因するモジュール性の欠如に陥ります。
'classReturn'もオーバーロードしないのはなぜですか?ちょうどそれをクラスのメンバーにしてください。 – augustss
ところで、私は 'x + y - x * y'は対称性を強調していると思いますが、バージョンに数値的な理由があるかもしれません。 – augustss
あなたのコメントで何かが失われました。 – augustss