8

Haskell でいくつかの算術演算子を再定義して、拡張性と汎用性を高めたいと考えています。

例えば

class Mul a b c | a b -> c where
    (*) :: a -> b -> c

これと組み合わせて動作するようです

import Prelude hiding ((*))

標準*演算子を非表示にします。もちろん、通常の乗算​​もすべて機能する必要があるため、次のように定義する必要があります。

instance (Num t) => Mul t t t where
    (*) = ??

*ここで元の演算子にアクセスするにはどうすればよいですか(機能しません)、 Monomopism Restrictionと競合しないPrelude.(*)ようにインスタンス タイプを定義するにはどうすればよいですか?1 * 1


編集-

import qualified

良いヒントです、ありがとう。

しかし残念ながら、これにより、すべての標準メソッドを明示的にスコープに入れる必要がありました。特定のバインディングを再定義して、残りを変更しないようにしたいだけです。

では、両方の組み合わせはありますか?何かのようなもの

import Prelude qualified ((*))
4

4 に答える 4

24

編集された質問に答える:

できるよ

import Prelude hiding ((*))
import qualified Prelude as P

(*)通常の方法と接頭辞を(*)使用する方法を除いて、すべての Prelude 機能にアクセスするには:P

x = 5 + 3   -- works
y = 5 P.* 3 -- works
z = 5 * 3   -- complains about * not being in scope
于 2010-03-05T18:03:36.860 に答える
4

インスタンス

instance (Num t) => Mul t t t where
    (*) = ??

Mul t t tallow の拡張機能を悪用することなく、最初に定義した目的を大幅に無効にします{-# LANGUAGE OverlappingInstances #-}

残念ながら、痛みを伴う場合の「正しい」答えは、インスタンスごとに調べて実行することです

import Prelude hiding ((*))
import qualified Prelude 

instance Mul Int Int Int where
    (*) = (Prelude.*)

instance Mul Double Double Double where
    (*) = (Prelude.*)


instance Mul Int Double Double where
    ...

instance Mul (Complex Float) (Complex Double) (Complex Double)
    ...

そうしないと、インスタンス ヘッドがコンパイラで解決される方法 (バックトラッキングが行われない) により、新しいインスタンスを実際に使用するときにコンパイルが失敗する可能性があります。

そうは言っても、考えもしなかったインスタンスの痛みを少なくとも和らげることはできます。

newtype Other a = Other a

instance Num a => Mul (Other a) (Other a) (Other a) where
    Other a * Other b = Other (a Prelude.* b)

これにより、Mul と他のすべてのクラスを自分で定義したくない場合は、少なくとも newtype ラッパーを使用できるようになります。

于 2010-03-07T07:41:50.037 に答える
3

このようなことを行う試みがいくつかありました。

まず、

元の * 演算子にアクセスするにはどうすればよいですか (Prelude.(*) は機能しません)

次のことを行う必要があります。

import qualified Prelude 

たとえば (Prelude.*) を使用できるようになりました。これは、「LANGUAGE NoImplicitPrelude」よりも攻撃的ではありません。これにより、>>= などのローカルでの使用が定義に再バインドされます。

以下は、他の人々の別の前奏曲の例です。

于 2010-03-05T17:34:37.803 に答える
2

私は最初の質問に答えることができます。(*) 演算子を非表示にすると、実際には非表示になるため、取得できません。ただし、Prelude 修飾をインポートできます。

import qualified Prelude as P

foo = 3 P.* 14 -- == 42

それはあなたが望むことだと思います。

于 2010-03-05T17:40:23.673 に答える