3

Haskell で、多相型を取り、多相型を返すことができる関数を持つことは可能ですか?

たとえば、値を取り、値が型の場合は Int を返し、型のFoo場合は Stringを返す関数が必要です。Bar

data Foo = One | Two | Three deriving (Show, Read)
data Bar = This | That | TheOther deriving (Show, Read)

doSomething :: Either Foo Bar -> Either Int String
doSomething var = if (typeOf var) == Int then 123 else "string"

このようなことは可能ですか?そうでない場合、タイプに基づいて別の関数にルーティングするためのベスト プラクティスは何ですか?

4

2 に答える 2

5

最初にあなたが記述したものと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 -> Intand Bar -> String)

これは深いトピックです (依存型の境界線 ;)) ですが、クラスを持つ型ファミリは理解するのが難しくないと思います。

PolyMap私が使用したアイデアは、関数を提供するクラスを用意するpolyMapことです (任意の名前を付けることができます -など)。出力タイプは、インスタンスに記載されているようにforおよびforであるマッピングをdoSomething使用して入力タイプに依存します-宣言。To kIntFooStringBar


署名用のもう 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"
于 2015-11-25T06:40:09.123 に答える
3

doSomethingドメインからコドメインへの機能的な依存関係を使用して、ドメインとコドメインの両方の型をキーとする型クラスを入れることができます。

{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}
{-# LANGUAGE FlexibleInstances  #-} -- if one of your `to` really is `String`
class DoSomething from to | from -> to where
    doSomething :: from -> to

instance DoSomething Foo Int where -- ...
instance DoSomething Bar String where -- ...

タイプファミリベースのソリューションと比較して、これには、コドメインもドメインを一意に決定する場合、別の機能依存関係を追加できるという利点がありますto -> from。型ファミリーがそれをモデル化する良い方法を提供するとは思いません。

于 2015-11-25T06:41:10.487 に答える