我正在练习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
似乎使用type
或newtype
给了我相同的“表现”(即阅读上面的链接)但是'newtype'给了我更强的类型安全性,例如:我可以传递任何{{ 1}}函数对于Int -> Bool
的函数,但在定义为type Set = Int -> Bool
时必须传递Set'
。
newtype Set' = Set' (Int -> Bool)
答案 0 :(得分:6)
是的,它就像
一样简单instance Show Set where show = toString
虽然您需要启用TypeSynonymInstances
和FlexibleInstances
。完整的文件如下所示:
{-# 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) ++ "}"