Haskell:如何为类型Set = Int定义实例Show Set - >布尔

时间:2013-09-30 04:20:42

标签: haskell typeclass

我正在练习Martin Odersky的Scala和Haskell的“Scala中的函数编程原理”课程。 对于“作为函数设置”练习,我定义了一个“toString”函数:

import Data.List (intercalate)

type Set = Int -> Bool

contains :: Set -> Int -> Bool
contains s elem = s elem

bound = 1000

toString :: Set -> String
toString s =
    let xs = [(show x) | x <- [(-bound) .. bound], contains s x]
    in "{" ++ (intercalate "," xs) ++ "}"

-- toString (\x -> x > -3 && x < 10)
-- => "{-2,-1,0,1,2,3,4,5,6,7,8,9}"

能够定义:

会很棒
instance Show Set where
    show Set = ...

但是定义需要引用并调用函数thqt表示Set(即,参见'toString'函数)。

是否有可用于定义'Show Set'的Haskell魔法?

根据反馈更新:

尝试两种解决方案建议并阅读后 Difference between `data` and `newtype` in Haskell 似乎使用typenewtype给了我相同的“表现”(即阅读上面的链接)但是'newtype'给了我更强的类型安全性,例如:我可以传递任何{{ 1}}函数对于Int -> Bool的函数,但在定义为type Set = Int -> Bool时必须传递Set'

newtype Set' = Set' (Int -> Bool)

2 个答案:

答案 0 :(得分:6)

是的,它就像

一样简单
instance Show Set where show = toString

虽然您需要启用TypeSynonymInstancesFlexibleInstances。完整的文件如下所示:

{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}

import Data.List (intercalate)

type Set = Int -> Bool

contains :: Set -> Int -> Bool
contains s elem = s elem

bound = 1000

toString :: Set -> String
toString s =
    let xs = [(show x) | x <- [(-bound) .. bound], contains s x]
    in "{" ++ (intercalate "," xs) ++ "}"

instance Show Set where show = toString

在ghci:

*Main> (\x -> x > -3 && x < 10) :: Set
{-2,-1,0,1,2,3,4,5,6,7,8,9}

但是,这有一些警告:即多态函数与给定实例不匹配。 (例如,上面的ghci示例中的类型归属:: Set是必需的。)

答案 1 :(得分:5)

您需要将Set设为新类型而不是类型同义词,如下所示:

newtype Set = Set { unSet :: Int -> Bool }

然后你可以把它变成任何类的实例,比如Show

instance Show Set where
    show (Set s) =
        let xs = [(show x) | x <- [(-bound) .. bound], contains s x]
        in "{" ++ (intercalate "," xs) ++ "}"