最初にあなたが記述したものとEither Int String
署名が一致していないようです-最初に記述したものを試します(出力タイプを入力タイプで選択します):
タイプファミリーで試していると私が思うことと非常によく似たことができます:
{-# LANGUAGE TypeFamilies #-}
module SO where
data Foo = One | Two | Three deriving (Show, Read)
data Bar = This | That | TheOther deriving (Show, Read)
class PolyMap k where
type To k :: *
polyMap :: k -> To k
instance PolyMap Foo where
type To Foo = Int
polyMap _ = 123
instance PolyMap Bar where
type To Bar = String
polyMap _ = "string"
例:
λ> polyMap One
123
λ> polyMap That
"string"
いくつかの説明
私があなたが望むのは、型マッピング/関数を持つことです (すぐに使用できる実行時チェックはありませんtypeOf
。これにより、代わりに優れた型チェックのサポートが得られます)。基本的に 2 つの方法があります (私は承知しています)
どちらも (特に) 何らかの言い方をする手段を提供します: タイプを取得した場合、AI は関連付けられたタイプ B が何であるかを言うことができます ( Foo -> Int
and Bar -> String
)
これは深いトピックです (依存型の境界線 ;)) ですが、クラスを持つ型ファミリは理解するのが難しくないと思います。
PolyMap
私が使用したアイデアは、関数を提供するクラスを用意するpolyMap
ことです (任意の名前を付けることができます -など)。出力タイプは、インスタンスに記載されているようにforおよびforであるマッピングをdoSomething
使用して入力タイプに依存します-宣言。To k
Int
Foo
String
Bar
署名用のもう 1 つはさらに簡単です。
doSomething :: Either Foo Bar -> Either Int String
doSomething (Left _) = Left 123
doSomething (Right _) = Right "string"
例:
λ> doSomething (Left One)
Left 123
λ> doSomething (Right That)
Right "string"