我在“了解你一个haskell”中阅读了关于该主题的章节,并尝试在不同的网站上找到一些提示 - 但仍然无法解决以下任务。
我m a haskell newbie (6 weeks of "experience") and it
是我第一次使用实例。
所以这是任务,我的代码必须通过HUnit测试和结束。我试图实现这些实例,但似乎我错过了那里的东西。希望你能帮我! THX
module SemiGroup where
{-
A type class 'SemiGroup' is given. It has exactly one method: a binary operation
called '(<>)'. Also a data type 'Tree' a newtype 'Sum' and a newtype 'Max' are
given. Make them instances of the 'SemiGroup' class.
The 'Tree' instance should build a 'Branch' of the given left and right side.
The 'Sum' instance should take the sum of its given left and right side. You need
a 'Num' constraint for that.
The 'Max' instance should take the maximum of its given left and right side. You
also need a constraint for that but you have to figure out yourself which one.
This module is not going to compile until you add the missing instances.
-}
import Test.HUnit (runTestTT,Test(TestLabel,TestList),(~?=))
-- | A semigroup has a binary operation.
class SemiGroup a where
(<>) :: a -> a -> a
-- Leaf = Blatt, Branch = Ast
-- | A binary tree data type.
data Tree a = Leaf a
| Branch (Tree a) (Tree a)
deriving (Eq,Show)
-- | A newtype for taking the sum.
newtype Sum a = Sum {unSum :: a}
-- | A newtype for taking the maximum.
newtype Max a = Max {unMax :: a}
instance SemiGroup Tree where
(<>) x y = ((x) (y))
instance SemiGroup (Num Sum) where
(<>) x y = x+y
instance SemiGroup (Eq Max) where
(<>) x y = if x>y then x else y
-- | Tests the implementation of the 'SemiGroup' instances.
main :: IO ()
main = do
testresults <- runTestTT tests
print testresults
-- | List of tests for the 'SemiGroup' instances.
tests :: Test
tests = TestLabel "SemiGroupTests" (TestList [
Leaf "Hello" <> Leaf "Friend" ~?= Branch (Leaf "Hello") (Leaf "Friend"),
unSum (Sum 4 <> Sum 8) ~?= 12,
unMax (Max 8 <> Max 4) ~?= 8])
我尝试过类似的事情:
class SemiGroup a where
(<>) :: a -> a -> a
-- Leaf = Blatt, Branch = Ast
-- | A binary tree data type.
data Tree a = Leaf a
| Branch (Tree a) (Tree a)
deriving (Eq,Show)
-- | A newtype for taking the sum.
newtype Sum a = Sum {unSum :: a}
-- | A newtype for taking the maximum.
newtype Max a = Max {unMax :: a}
instance SemiGroup Tree where
x <> y = Branch x y
instance Num a => SemiGroup (Sum a) where
x <> y = x+y
instance Eq a => SemiGroup (Max a) where
x <> y = if x>y then x else y
但还有一些失败!至少是“chi”提到的包裹/展开的东西。但我不知道。也许是另一个暗示? :/
答案 0 :(得分:1)
我没有看到如何将Tree a
转变为半群(除非必须将其视为某种东西)。
对于Sum a
newtype,您需要要求a
属于Num
类。然后,您需要围绕值包装/解包Sum
构造函数,以便:1)您将两个Sum a
,2)转换为两个a
,这是一个合适的类型其中+
已定义,3)您对它们求和,4)您将结果转换回Sum a
。
您可以尝试从
开始自己编写以上代码instance Num a => Semigroup (Sum a) where
x <> y = ... -- Here both x and y have type (Sum a)
Max a
实例将需要类似的包装/解包代码。
进一步提示:要将Sum a
展开到a
,您可以使用该功能
unSum :: Sum a -> a
将a
打包成Sum a
,而不是
Sum :: a -> Sum a
请注意,Sum, unSum
声明已经隐式定义了两个函数newtype
,因此您不必定义它们(您已经这样做了)。
或者,您可以使用模式匹配来展开您的值。而不是定义
x <> y = ... -- x,y have type Sum a (they are wrapped)
你可以写
Sum x <> Sum y = ... -- x,y have type a (they are unwrapped)
答案 1 :(得分:0)
注意类型。无论是手动还是在GHCi的帮助下,找出你正在编写的函数的类型 - 你会发现它们与类型类实例所需的类型不匹配。您将使用包装和展开来调整类型,直到它们工作。