2012-03-27 13 views
2

Read a => String -> a型の関数を持っていますが、aが例えばStringの場合、同じ名前で別の関数を持つことはできますか?これを可能にするGHCの拡張はありますか?Haskellの関数型特殊化

何かのように:(広告をHaskellで

{-# LANGUAGE FlexibleInstances #-} 
{-# LANGUAGE UndecidableInstances #-} 
{-# LANGUAGE TypeSynonymInstances #-} 
{-# LANGUAGE OverlappingInstances #-} 

class SpecialRead a where 
    specialRead :: String -> a 

instance Read a => SpecialRead a where 
    specialRead = read 

instance SpecialRead String where 
    specialRead = id 

main = do 
    print (specialRead "10" :: Int) 
    print (specialRead "10" :: String) 
+0

パフォーマンスについて懸念しているのであれば、これらの種類のものはコンパイラによって最適化されるはずです。 – leftaroundabout

+0

私はパフォーマンスについて心配していません。文字列の前後に引用符は必要ない 'read'のバージョンが必要ですが、それ以外の場合は通常の' read'として動作します。 –

+0

質問はhttp://stackoverflow.com/questions/9870962/haskell-making-a-superclass-of-num/とまったく同じ問題に対処しています。いくつかの答えが役に立つかもしれません。 –

答えて

12

、過負荷にこのような機能:

f :: Read a => String -> a 
f = read 

f :: String -> String 
f = id 
4

私はそれが動作するようになったが、私は疑問言語オプションの束をオンにする必要がありました-hoc多型)は、複数の型の下で同じ名前をバインドするのではなく、型クラスを使用することによって実現されます。

{-# LANGUAGE FlexibleInstances, TypeSynonymInstances #-} 

class F a where f :: String -> a 

instance F String where f = id 
instance F Int where f = read 
instance F Char where f = read 
instance F Float where f = read 
-- etc. 

さて、fFのインスタンスが宣言された任意の型を操作することができます。

残念ながら、あなたは次のように逃げることができません。

instance Read a => F a where f = read 

を多分unintuitively、これはReadのインスタンスを持っているタイプのためFのインスタンスを宣言していません。 GHCはインスタンス宣言の先頭(=>の右側の部分)のみを使用してインスタンスを解決するため、実際にはすべてのタイプaFのインスタンスであると宣言しますが、それ以外の場合はfを呼び出すタイプエラーになりますReadのインスタンス

UndecidableInstances拡張機能を有効にするとコンパイルされますが、これは他の問題につながります。あなたが本当に冒険したくないウサギの穴です。

代わりに、fを操作する予定の個々のタイプごとにFのインスタンスを宣言する必要があります。これは、このような単純なクラスのために非常に負担はありませんが、GHCの最新バージョンを使用している場合、あなたはそれが少し楽にするために、次を使用することができます任意のタイプのため、

{-# LANGUAGE DefaultSignatures #-} 

class F a where f :: String -> a 
       default f :: Read a => String -> a 
       f = read 

Readのインスタンスは、明示的fの実装を提供することなく、Fのそのインスタンスを宣言することがあります。Readのインスタンスなしには、いかなる種類のについては

instance F Int 
instance F Char 
instance F Float 
-- etc. 

を、あなたはまだのための明示的な実装を作成する必要があります。

+5

'FlexibleInstances'と' TypeSynonymInstances'は議論の余地がありません。彼らは、ハスケル標準によって課せられたいくつかの制限を緩和しますが、心配するものではありません。'UndecidableInstances'と' OverlappingInstances'は危険な領域ですが、あなたが何をしているのか分からない限り、一般的に避けるべきです。 – bitbucket

関連する問題