3

Haskell では、なぜこれがコンパイルされるのですか?

splice :: String -> String -> String
splice a b = a ++ b
main = print (splice "hi" "ya")

しかし、これはしません:

splice :: (String a) => a -> a -> a
splice a b = a ++ b
main = print (splice "hi" "ya")

>> Type constructor `String' used as a class

私はこれらが同じものだと思っていたでしょう。タイプ名を3回繰り返さないようにする2番目のスタイルを使用する方法はありますか?

4

5 に答える 5

13

タイプの=>構文はタイプクラス用です

あなたが言うとき、あなたはそれがであると言っているf :: (Something a) => aではなく、あなたはそれが「グループの」タイプであると言っているのです。a SomethingSomething

たとえば、は型クラスであり、やNumなどの型が含まれます。それでもタイプがないので言えないIntFloatNum

f :: Num -> Num
f x = x + 5

しかし、私はどちらかを言うことができます

f :: Int -> Int
f x = x + 5

また

f :: (Num a) => a -> a
f x = x + 5
于 2012-05-07T19:10:28.803 に答える
3

実際には、次のことが可能です。

Prelude> :set -XTypeFamilies
Prelude> let splice :: (a~String) => a->a->a; splice a b = a++b
Prelude> :t splice
splice :: String -> String -> String

これは等式制約を使用します~。しかし、私はそれを避けたいと思います。単に書くよりもはるかに短くはString -> String -> Stringなく、理解するのが難しく、コンパイラが解決するのがより困難です。

于 2012-05-07T19:28:47.737 に答える
3

タイプ名を3回繰り返さないようにする2番目のスタイルを使用する方法はありますか?

型シグネチャを単純化するために、型シノニムを使用できます。たとえば、次のように書くことができます

type S = String
splice :: S -> S -> S

または何かのような

type BinOp a = a -> a -> a
splice :: BinOp String

ただし、 のような単純なものについては、String -> String -> String入力することをお勧めします。型シノニムは、型シグネチャを読みやすくするために使用する必要があります。

この特定のケースでは、型シグネチャを次のように一般化することもできます。

splice :: [a] -> [a] -> [a]

要素が文字であることにまったく依存しないためです。

于 2012-05-07T20:29:58.027 に答える
1

このLearnYouaHaskellの章で説明が役立つかもしれません。

于 2012-05-07T19:10:47.483 に答える
1

ええと...Stringは型であり、クラスとして使用しようとしていました。

関数のポリモーフィック バージョンの例が必要な場合は、次spliceを試してください。

import Data.Monoid

splice :: Monoid a=> a -> a -> a
splice = mappend

EDIT : したがって、ここでの構文は、 の左側に表示される大文字の単語は、 の右側に表示される変数を制約する=>クラス=>です。右側の大文字はすべて型の名前です

于 2012-05-07T18:17:44.827 に答える