2 つのパラメーターを受け入れ、最初のパラメーターが 2 番目のパラメーターの前に表示される必要がある場合は True、それ以外の場合は False を返す単純な min 関数を実装しようとしています。
min :: a -> a -> Bool
min a b = if a < b then True else False
私は得る:
No instance for (Ord a)
arising from a use of `<'
2 つのパラメーターを受け入れ、最初のパラメーターが 2 番目のパラメーターの前に表示される必要がある場合は True、それ以外の場合は False を返す単純な min 関数を実装しようとしています。
min :: a -> a -> Bool
min a b = if a < b then True else False
私は得る:
No instance for (Ord a)
arising from a use of `<'
ドキュメントを見ると、の型(<)
が次のように指定されていることがわかります。
(<) :: a -> a -> Bool
これは誤解を招く!
型宣言は、型クラス定義に表示されます。
class Eq a => Ord a where ...
したがって、フルタイプは
(<) :: Ord a => a -> a -> Bool
ちなみに、 ghci に type は何かと尋ねると、答えてくれます(<)
。
Prelude> :t (<)
(<) :: (Ord a) => a -> a -> Bool
また、同じ型クラスに , という関数が既に存在することに注意してくださいmin
。
min :: Ord a => a -> a -> a
min
したがって、元の を非表示にしない限り、関数を呼び出すことはできませんmin
。(方法を説明するつもりはありません。代わりに、関数に別の名前を使用してください。)
最後に、あなたは今持っています
min :: Ord a => a -> a -> Bool
min a b = if a < b then True else False
Sarah が指摘しているように、if blah then True else False
は と同じblah
であるため、より明確に単純化できます。
min :: Ord a => a -> a -> Bool
min a b = a < b
現在、Haskell の演算子は変な名前の関数にすぎません --- これは
min :: Ord a => a -> a -> Bool
min a b = (<) a b
これをさらに単純化できます。
min :: Ord a => a -> a -> Bool
min = (<)
だから、あなたmin
はの別の名前です(<)
。<
あなたの代わりにオリジナルを使用してみませんmin
か?
これにはすでに2つの答えがありますが、重要な点が欠けていると思います:
型シグネチャが必要な理由は(Ord a) =>
、関数に「入れる」ことができる型を制限する必要があるためです。
function を定義するとき、関数は任意の型のデータを取り、同じ型の値を返すfunction :: a -> a
と言っています。
これの良い例は次のとおりです。任意のhead :: [a] -> a
タイプのリストが与えられた場合、 head はリストの最初の引数を返します。これは、 head が実際にはデータ自体に「接触」していないためです。そのため、それが何であるかはまったく問題になりません。
しかし、あなたの状況はそうではありません:データ型Countriesがあると想像してください:
data Countries = USA | Nigeria | China | Canada -- yes, I know there are a few missing
min USA Canada
またはと言うのは意味がありませんUSA < Canada
。
したがって、関数をこの方法で比較できる型に制限する必要があります: Ord
(つまり順序付けられた) 型クラスのインスタンスを持つ型です。それらを制限する方法は(Ord a) =>
、型シグネチャの前に書くことです。
動作させるには型制約が必要です<
:
min :: Ord a => a -> a -> Bool
-- ^^^^^