2016-09-08 10 views
3

は、次のデータ型GADT用のモノイドインスタンスを作成することはできますか?

私はそれのためモノイドインスタンスを導出する方法を
{-# LANGUAGE GADTs #-} 

data Response a where 
    ResponseMap :: HashMap Text (Sum Int) -> Response (HashMap Text (Sum Int)) 
    ResponseSum :: Sum Int -> Response (Sum Int) 

を考えると?コンストラクタ

(ResponseSum v1) `mappend` (ResponseSum v2) = undefined 
    (ResponseMap v1) `mappend` (ResponseMap v2) = undefined 

とのmappend私ができるパターンマッチの定義について簡単に値を組み合わせるが、それは実際に可能だ、または理にかなっている場合、私は私がmemptyを実装する方法を参照するか、ないのですか?

+3

あなたのGADTは実際にGADTではありません。 'newtype Response a = Response a'と似ていますが、' a'は 'Sum Int'や' HashMap Text(Sum Int) 'しかないので便利ではありません。 'newtype'を使用する場合は' GeneralizedNewtypeDeriving'を使用して無料の 'Monoid'インスタンスを取得することができます –

+0

@BenjaminHodgsonもし私がnewtypeとして' Response a'を定義したら、それを知る関数を定義する方法がありますそれは何のために働いていますか? – ppb

+4

私は古風な方法 'f ::レスポンス(Sum Int) - > Foo'を好きです –

答えて

8

mempty :: Response aを定義することができないため、気づいたとおり、instance Monoid (Response a)を指定することはできません。何故なの?さて、memptyは、のタイプResponse aa(例えば、Boolを含む)タイプでなければなりません。しかし、タイプResponse BoolResponse (HashMap Text (Sum Int))およびResponse (Sum Int)の値を構築することはできません。したがって、memptyを作成することはできません。これはmappendの問題ではありません。で、Response aとなっているので、あなたが与えられたのはaです。しかし、memptyには何も分析することはありません。

あなたは何をすることができますか?まず、instance Semigroup (Response a)を提供することができます。セミグループは正確にはmemptyのないモノイドですので、これはあなたが欲しいものです。 GHC 8では、baseパッケージのモジュールData.Semigroupにこのタイプのクラスがあります。それ以前には、同じモジュール名を使用してsemigroupsパッケージを使用する必要があります。 mappendの代わりに、2進演算子(<>)を使用します。だから、あなたはまた、あなたが構築できるタイプの指標のために特定Monoidのインスタンスを提供することができます

import Data.Semigroup 
import Data.Monoid hiding ((<>)) 

-- ... 

instance Semigroup (Response a) where 
    ResponseMap v1 <> ResponseMap v2 = ResponseMap $ v1 <> v2 
    ResponseSum v1 <> ResponseSum v2 = ResponseSum $ v1 <> v2 

を持っていると思います。 FlexibleInstancesでは、それはあなたが単位であり、あなたがMonoidインスタンスを持っているものを知っていますか例のために、今すぐ

{-# LANGUAGE FlexibleInstances #-} 

instance Monoid (Response (HashMap Text (Sum Int))) where 
    mempty = ResponseMap mempty 
    mappend = (<>) 

instance Monoid (Response (Sum Int)) where 
    mempty = ResponseSum mempty 
    mappend = (<>) 

のように見えます。

関連する問題