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

har*_*arr 1 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}"
Run Code Online (Sandbox Code Playgroud)

能够定义:很高兴:

instance Show Set where
    show Set = ...
Run Code Online (Sandbox Code Playgroud)

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

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

根据反馈更新:

在尝试了两个建议的解决方案并在Haskell中读取 `data`和`newtype`之间的区别之后 ,似乎使用typenewtype给我相同的"性能"(即,阅读上面的链接)但是'newtype'给了我更强的类型安全性,例如:我可以将任何Int -> Bool函数传递给函数,type Set = Int -> Bool但必须Set'在定义时传递一个函数newtype Set' = Set' (Int -> Bool).

{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}

import Data.List (intercalate)

bound = 1000

-- ALTERNATE #1

type Set = Int -> Bool

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

intersect :: Set -> Set -> Set
intersect s t = \x -> s x && t x

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

instance Show Set where show = toString

-- ALTERNATE #2

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

contains' :: Set' -> Int -> Bool
contains' (Set' s) elem = s elem

intersect' :: Set' -> Set' -> Set'
intersect' (Set' s) (Set' t) = Set' (\x -> s x && t x)

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

anyIntBoolFun1 = \x -> -10 < x
anyIntBoolFun2 = \x ->   x < 0
setIntBoolFun1 = Set' anyIntBoolFun1
setIntBoolFun2 = Set' anyIntBoolFun2

main = do
    putStrLn $ show $ intersect  anyIntBoolFun1 anyIntBoolFun2
    putStrLn $ show $ intersect' setIntBoolFun1 setIntBoolFun2

-- *Main> main
-- {-9,-8,-7,-6,-5,-4,-3,-2,-1}
-- {-9,-8,-7,-6,-5,-4,-3,-2,-1}
Run Code Online (Sandbox Code Playgroud)

Dan*_*ner 6

是的,它就像

instance Show Set where show = toString
Run Code Online (Sandbox Code Playgroud)

虽然你需要打开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
Run Code Online (Sandbox Code Playgroud)

在ghci:

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

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


Gab*_*lez 5

您需要创建Set一个newtype而不是类型同义词,如下所示:

newtype Set = Set { unSet :: Int -> Bool }
Run Code Online (Sandbox Code Playgroud)

然后你可以使它成为任何类的实例,如Show:

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