如何根据上下文创建不同的类实例?

时间:2018-02-27 12:00:08

标签: haskell types ghc

我有一些简单的类和一些用于各种数据类型和上下文的实例。这是一个部分工作的案例:

{-# LANGUAGE FlexibleInstances, UndecidableInstances, IncoherentInstances  #-}

class Neighbors a where
     (~~) :: a -> a -> Bool

instance Neighbors Int where
  x ~~ y = (abs (x-y) == 1)

instance (RealFloat a) => Neighbors a where
  x ~~ y = (abs(x-y) < 1.0)

有一个缺点是我必须对Int使用类型限制:

*Main> (1::Int) ~~ (2::Int)
True

但是,如果我只想使用上下文,我的第二个脚本根本不起作用:

{-# LANGUAGE FlexibleInstances, UndecidableInstances, IncoherentInstances  #-}

class Neighbors a where
     (~~) :: a -> a -> Bool

instance (Integral a) => Neighbors a where
  x ~~ y = (abs(x-y) == 1)

instance (RealFloat a) => Neighbors a where
  x ~~ y = (abs(x-y) < 1.0)

错误是:

Neighborhood.hs:7:10: error:
    Duplicate instance declarations:
      instance [incoherent] Integral a => Neighbors a
        -- Defined at Neighborhood.hs:7:10
      instance [incoherent] RealFloat a => Neighbors a
        -- Defined at Neighborhood.hs:10:10
Failed, modules loaded: none.

但我想为这些不同的上下文定义不同的实例:Integral和RealFloat。如何在一个文件中执行此操作?

1 个答案:

答案 0 :(得分:1)

您可以在以下文件中执行此操作:

$.ajax({
    url: '@Url.Action("DeleteConfirm","Contestant")',
    type: "POST",
        dataType: "html",
        data: JSON.stringify(parameter),
        contentType: 'application/json; charset=utf-8',
        success: function (data) {
            debugger;
            $("div.modal-content").empty();
            $("div.modal-content").html(data);
            $("#myModal").modal();
        }
    });

我知道你不想为每个类型的构造函数编写一个实例;但这仍然是问题的正确答案,因为类型构造函数是Haskell类型类派遣的方式。

您可以通过定义

来减少一些重复
instance Neighbors Int     where x ~~ y = abs (x-y) == 1
instance Neighbors Double  where x ~~ y = abs (x-y) < 1
instance Neighbors Float   where x ~~ y = abs (x-y) < 1
instance Neighbors CDouble where x ~~ y = abs (x-y) < 1
instance Neighbors CFloat  where x ~~ y = abs (x-y) < 1
instance RealFloat a => Neighbors (Identity a) where x ~~ y = abs (x-y) < 1
instance RealFloat a => Neighbors (Const a b)  where x ~~ y = abs (x-y) < 1

并在实例中提供neighborsDef :: (Num a, Ord a) => a -> a -> Bool neighborsDef x y = abs (x-y) < 1

事实上,根据问题略微踩到问题的一边,我怀疑你根本不想要一个新的类型类。也许以下两个定义中的一个适合您:

(~~) = neighborsDef