10

短い検索では答えを見つけることができなかったので、私はその存在に疑問を抱き始めました。質問は簡単です。次のようなポリモーフィック関数を作成したいと思います。

f :: String -> String
f s = show (length s)

f :: Int -> String
f i = show i

データ型ごとに異なる方法で定義された関数を意味します。出来ますか?はいの場合、どのように?

4

2 に答える 2

22

Haskellには2つのポリモーフィズムのフレーバーがあります。

  • パラメータ多型; と
  • 有界ポリモーフィズム

1つ目は最も一般的なものです。関数は、その型パラメーターの少なくとも1つで、すべての型に対して均一に動作する場合、パラメトリックに多形です。

たとえば、関数lengthは多態性です。リストに格納されているタイプに関係なく、リストの長さを返します。

length :: [a] -> Int

多型は小文字の型変数で示されます。

これで、特定のタイプのセットに対して必要なカスタム動作がある場合は、ポリモーフィズム(「アドホック」とも呼ばれます)が制限されています。Haskellでは、このために型クラスを使用します。

このクラスは、一連のタイプで使用できる関数を宣言します。

class FunnyShow a where
    funnyshow :: a -> String

次に、気になるタイプごとにインスタンスを定義できます。

instance FunnyShow Int where
    funnyshow i = show (i+1)

そして多分:

instance FunnyShow [Char] where
   funnyshow s = show (show s)
于 2012-09-14T19:21:11.990 に答える
14

型族を使用して同様のことを実現する方法は次のとおりです。

同じ戻り型がある場合は、型族を使用せずに、Donが提案するように型クラスのみを使用して動作を実現できます。

ただし、インスタンスごとに異なる戻り型など、より複雑なアドホック多相性をサポートする場合は、型ファミリーを使用することをお勧めします。

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE TypeFamilies #-}

class F a where
    type Out a :: * 
    f :: a -> Out a

instance F String where  
    type Out String = String
    f = show . length

instance F Int where 
    type Out Int = String 
    f = show 

instance F Float where 
    type Out Float = Float
    f = id  

ghciで

*Main> f (2::Int)
"2"

*Main> f "Hello"
"5"

*Main> f (2::Float)
2.0
于 2012-09-14T19:27:29.333 に答える