哈斯克尔 - 也许是其中之一

时间:2014-06-25 11:03:37

标签: haskell either

-- | 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 aa ?!

我一般不知道如何编写这些函数。

4 个答案:

答案 0 :(得分:15)

鉴于我认为这是作业,我不会回答,但给出重要提示:

如果您在hoogle(http://www.haskell.org/hoogle/)上查找定义 你找到了

data Bool = True | False
data Either a b = Left a | Right b

这意味着Bool只能是TrueFalse,但Either a b可以是Left aRight 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 7Nothing

同样,Either Int Char类型的内容可以是Left 5Right 'c'

Either Int Int类型的内容可以是Left 7Right 4

类型为Either Int Char的内容可能是IntChar,但Either Int Int类型的内容可能是Int或{{1} }}。您无法选择Int以外的任何内容,但您会知道它是Int还是Left

为什么你被问到/背后的想法

如果您的某些内容属于Right,那么数据(例如Either a a中的5)始终为Left 5类型,您只是标记了它aLeft。如果您有Right类型的内容(Bool,a) - 数据(例如a中的5)始终是同一类型,并且您已将其与{{1}配对}或(True,5)

两个可能看起来不同但实际上具有相同内容的事物的数学词是“同构的”。你的导师要求你写一对显示这种同构的函数。如果FalseTrue执行pairWithBoolToEither . eitherToPairWithBool所做的事情,即不做任何更改,那么您的答案会更好。事实上,我刚刚在你的问题中发现了这些评论,它说它们应该是逆向的。在你的写作中,你应该通过在像

这样的ghci中进行测试来证明这一点
eitherToPairWithBool . pairWithBoolToEither

反之亦然。

(如果您还没有看到,idghci> 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),因此我们可以Boola,他们会给我们两个(可能是不同的)类型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 -> apairToFunctionFromBool (x,y) True = .... pairToFunctionFromBool (x,y) False = .... 子句定义一个名为let的函数,其中where<有点像:

f

玩得开心。乱七八糟。

答案 1 :(得分:5)

或许有用的是注意Either a b也称为ab类型的副产品或总和。实际上现在通常使用

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 xRight 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在我看来毫无意义。

是的。尝试找出类型aEither a a之间的区别。 Eitherdisjoint union。一旦你理解了aEither a a之间的区别,你的家庭作业应该很容易与AndrewC的回答结合起来。

答案 3 :(得分:1)

请注意Either a b字面意思是这种类型的值可以是aa。听起来你实际上已经掌握了这个概念,但是你遗漏的部分是Either类型区分用Left构造的值和用Right构造的值。

对于第一部分,我的想法是Maybe要么Just要么Nothing - Nothing对应()因为两者都是&(Bool, a) #34;本质上是#34;数据类型只有一个可能的值。

Either a a对转换为True对背后的想法似乎有点棘手,但只需考虑FalseLeftRight之间的对应关系和(Bool -> a)

至于将(a, a)类型的函数转换为Bool对,这里有一个提示:考虑{{1}}只能有两种类型的事实,并记下该初始值函数参数可能看起来像。

希望这些提示可以帮助您开始使用。