-- | Convert a 'Maybe a' to an equivalent 'Either () a'. Should be inverse
-- to 'eitherUnitToMaybe'.
maybeToEitherUnit :: Maybe a -> Either () a
maybeToEitherUnit a = error "Not yet implemented: maybeToEitherUnit"
-- | Convert a 'Either () a' to an equivalent 'Maybe a'. Should be inverse
-- to 'maybeToEitherUnit'.
eitherUnitToMaybe :: Either () a -> Maybe a
eitherUnitToMaybe = error "Not yet implemented: eitherUnitToMaybe"
-- | Convert a pair of a 'Bool' and an 'a' to 'Either a a'. Should be inverse
-- to 'eitherToPairWithBool'.
pairWithBoolToEither :: (Bool,a) -> Either a a
pairWithBoolToEither = undefined -- What should I do here?
-- | Convert an 'Either a a' to a pair of a 'Bool' and an 'a'. Should be inverse
-- to 'pairWithBoolToEither'.
eitherToPairWithBool :: Either a a -> (Bool,a)
eitherToPairWithBool = undefined -- What should I do here?
-- | Convert a function from 'Bool' to 'a' to a pair of 'a's. Should be inverse
-- to 'pairToFunctionFromBool'.
functionFromBoolToPair :: (Bool -> a) -> (a,a)
functionFromBoolToPair = error "Not yet implemented: functionFromBoolToPair"
-- | Convert a pair of 'a's to a function from 'Bool' to 'a'. Should be inverse
-- to 'functionFromBoolToPair'.
pairToFunctionFromBool :: (a,a) -> (Bool -> a)
pairToFunctionFromBool = error "Not yet implemented: pairToFunctionFromBool"
我真的不知道该怎么做。我知道可能是什么,但我认为我也有问题,因为Either a a
在我的脑海里没有任何意义。 Either a b
会好的。这是a或b但是Either a a
是a
?!
我一般不知道如何编写这些函数。
答案 0 :(得分:15)
鉴于我认为这是作业,我不会回答,但给出重要提示:
如果您在hoogle(http://www.haskell.org/hoogle/)上查找定义 你找到了
data Bool = True | False
data Either a b = Left a | Right b
这意味着Bool
只能是True
或False
,但Either a b
可以是Left a
或Right b
。
表示您的功能应该是
pairWithBoolToEither :: (Bool,a) -> Either a a
pairWithBoolToEither (True,a) = ....
pairWithBoolToEither (False,a) = ....
和
eitherToPairWithBool :: Either a a -> (Bool,a)
eitherToPairWithBool (Left a) = ....
eitherToPairWithBool (Right a) = ....
与Maybe
Maybe a
由
data Maybe a = Just a | Nothing
因此Maybe Int
类型可能是Just 7
或Nothing
。
同样,Either Int Char
类型的内容可以是Left 5
或Right 'c'
。
Either Int Int
类型的内容可以是Left 7
或Right 4
。
类型为Either Int Char
的内容可能是Int
或Char
,但Either Int Int
类型的内容可能是Int
或{{1} }}。您无法选择Int
以外的任何内容,但您会知道它是Int
还是Left
。
为什么你被问到/背后的想法
如果您的某些内容属于Right
,那么数据(例如Either a a
中的5
)始终为Left 5
类型,您只是标记了它a
或Left
。如果您有Right
类型的内容(Bool,a)
- 数据(例如a
中的5
)始终是同一类型,并且您已将其与{{1}配对}或(True,5)
。
两个可能看起来不同但实际上具有相同内容的事物的数学词是“同构的”。你的导师要求你写一对显示这种同构的函数。如果False
和True
执行pairWithBoolToEither . eitherToPairWithBool
所做的事情,即不做任何更改,那么您的答案会更好。事实上,我刚刚在你的问题中发现了这些评论,它说它们应该是逆向的。在你的写作中,你应该通过在像
eitherToPairWithBool . pairWithBoolToEither
反之亦然。
(如果您还没有看到,id
由ghci> eitherToPairWithBool . pairWithBoolToEither $ (True,'h')
(True,'h')
定义,但$
的优先级非常低(f $ x = f x
),因此$
infixr 0 $
只是f . g $ x
,(f . g) $ x
是函数组合,所以(f . g) x
。这是保存一对括号的很多解释!)
当你不习惯它时,这可能有点令人兴奋。
.
你唯一可以匹配函数的东西只是像(f.g) x = f (g x)
这样的变量,所以我们需要做类似的事情
functionFromBoolToPair :: (Bool -> a) -> (a,a)
但我们可以用f
做些什么呢?那么,使用函数最简单的方法就是将它应用于一个值。我们可以使用functionFromBoolToPair f = ...
的价值是多少?好f
所以它需要f
并为您提供f :: (Bool -> a)
,因此我们可以Bool
或a
,他们会给我们两个(可能是不同的)类型f True
的值。现在这很方便,因为我们需要f False
值,不是吗?
接下来看看
a
我们可以为类型a
执行的模式匹配类似于pairToFunctionFromBool :: (a,a) -> (Bool -> a)
,因此我们需要
(a,a)
但我们怎样才能在右侧返回一个函数(x,y)
?
我认为有两种方法可以让您找到最简单的方法。一个是要注意,因为pairToFunctionFromBool (x,y) = ....
是正确的关联,类型(Bool -> a)
与->
相同所以我们实际上可以移动我们想要返回的函数的参数=标志,像这样:
(a,a) -> (Bool -> a)
另一种感觉可能更容易的方法是使(a,a) -> Bool -> a
或pairToFunctionFromBool (x,y) True = ....
pairToFunctionFromBool (x,y) False = ....
子句定义一个名为let
的函数,其中where
<有点像:
f
玩得开心。乱七八糟。
答案 1 :(得分:5)
或许有用的是注意Either a b
也称为a
和b
类型的副产品或总和。实际上现在通常使用
type (+) = Either
然后,您可以将Either a b
写为a + b
。
eitherToPairWithBool :: (a+a) -> (Bool,a)
现在常识要求我们将a + a
重写为2 ⋅ a
之类的内容。信不信由你,这正是你要改造的元组类型的意思!
解释:代数数据类型大致可以看作是“计算 1 可能的结构数”。所以
data Bool = True | False
有两个构造函数。所以(这不是有效的Haskell!)
type 2 = Bool
元组允许来自每个参数的构造函数的所有组合。例如,在(Bool, Bool)
中,我们有值
(False,False)
(False,True )
(True, False)
(True, True )
您已经猜到了:元组也被称为产品。所以类型(Bool, a)
基本上是2 ⋅ a
:对于每个值x :: a
,我们可以同时创建(False, x)
元组和(True, x)
元组,共计两倍于有x
个值。
Either a a
大致相同:我们始终同时将Left x
和Right x
作为可能的值。
type OnePlus = Maybe
maybeToEitherUnit :: OnePlus a -> () + a
eitherUnitToMaybe :: () + a -> OnePlus a
pairWithBoolToEither :: 2 ⋅ a -> a + a
eitherToPairWithBool :: a + a -> 2 ⋅ a
functionFromBoolToPair :: a² -> a⋅a
pairToFunctionFromBool :: a⋅a -> a²
1 对于几乎任何有趣的类型,实际上存在无限多的可能值,但这种天真的算法仍然让你惊讶不已。
答案 2 :(得分:1)
Either a a
在我看来毫无意义。
是的。尝试找出类型a
和Either a a
之间的区别。 Either
是disjoint union。一旦你理解了a
和Either a a
之间的区别,你的家庭作业应该很容易与AndrewC的回答结合起来。
答案 3 :(得分:1)
请注意Either a b
字面意思是这种类型的值可以是a
或a
。听起来你实际上已经掌握了这个概念,但是你遗漏的部分是Either
类型区分用Left
构造的值和用Right
构造的值。
对于第一部分,我的想法是Maybe
要么Just
要么Nothing
- Nothing
对应()
因为两者都是&(Bool, a)
#34;本质上是#34;数据类型只有一个可能的值。
将Either a a
对转换为True
对背后的想法似乎有点棘手,但只需考虑False
与Left
和Right
之间的对应关系和(Bool -> a)
。
至于将(a, a)
类型的函数转换为Bool
对,这里有一个提示:考虑{{1}}只能有两种类型的事实,并记下该初始值函数参数可能看起来像。
希望这些提示可以帮助您开始使用。