在Haskell中从'Maybe a'返回类型中获取'a'值

Unw*_*ast 5 haskell maybe

这很难解释,因为整个代码有一个相当大的背景细节,需要知道才能真正了解我所说的功能.但是我会尽力让我的主要观点得到解决,并希望它足够了.如果没有,请告诉我,我会添加更多信息.所以:

我有一个Haskell函数eval :: WExp -> Memory -> WValue,它有一堆不同的自身实例用于不同的情况.现在,有关的知识WExp,MemoryWValue是不相关的.我的问题是,对于特定的实例eval,我使用的是一个lookup函数,它接受eval(在这种情况下是一个字符串)的参数搜索该字符串的键值对列表.请注意,此lookup功能不是Prelude中包含的功能; 它是在.hs文件中自定义的.如果找到该字符串,则返回与其关联的值,但如果未找到,Nothing则返回该值.由于的Nothing情况下,该类型的lookup其实是Maybe a,这里a将是一个WValue在这种情况下.因为eval会返回a Maybe WValue,编译器显然会抱怨类型不是WValue.

同样,如果您需要有关这些其他类型的更多信息,我可以提供.我只想到可能有某种通用方法a从任何返回的函数中提取值Maybe a.如果没有,我想我会在别处寻找解决方案:)

CDR*_*CDR 10

您要查找的函数maybe在 Prelude 中定义。

如果表达式为 Nothing,您需要决定返回什么。假设您想""为 Nothing获取空字符串。那么下面的内容会让你跳出Maybe盒子。

Prelude> maybe "" id (Just "hello")
"hello"
Prelude> maybe "" id (Nothing)
""
Run Code Online (Sandbox Code Playgroud)


Ste*_*han 7

如果您知道查找成功,并且Maybe a确实是Just a,那么您可以简单地模式匹配:

let (Just val) = lookup ...
Run Code Online (Sandbox Code Playgroud)

在那里,你有你val::aMaybe a.请注意,这是不安全的代码,如果lookup返回a ,它会不正确地抛出错误Nothing.


dfe*_*uer 7

做这个

do
   input <- getUserInput
   result <- lookup input structure
   case result of
     Just a -> putStrLn $ "I'm so happy you chose "++show a++"."
     Nothing -> putStrLn $ "So sorry; "++input++" is not a valid option."
Run Code Online (Sandbox Code Playgroud)

不要这样做

do
   input <- getUserInput
   result <- lookup input structure
   case result of
     Just a -> putStrLn $ "I'm so happy you chose "++show a++"."
     Nothing -> error $ input ++ " is not a valid option."
Run Code Online (Sandbox Code Playgroud)

这很糟糕,因为如果用户输入错误,你的程序就会出现问题.

真的不要这样做

有一个函数被调用fromJust,试图从a中提取一个值,Maybe如果找到则抛出一个错误Nothing.看起来像

fromJust :: Maybe a -> a
fromJust (Just a) = a
fromJust Nothing = error "Oops, you goofed up, fool."
Run Code Online (Sandbox Code Playgroud)

这使得很难看出出了什么问题.

真的,真的不这样做

但如果你想玩火,你可以尝试它只是为了好玩.Maybe如果发现,这将尝试从a中获取一个值并且真正崩溃Nothing.通过"真正的崩溃"我的意思是,如果你很幸运,你会得到一个分段错误,如果你不是,你会在网上发布你的私钥.

{-# LANGUAGE GADTs, DataKinds, KindSignatures #-}
{-# OPTIONS_GHC -fno-warn-unused-binds #-}

module Unsafe.FromJust (unsafeFromJust) where

-- Clear sign of bad news
import Unsafe.Coerce (unsafeCoerce)

-- This creates a "closed kind" with types
-- 'JustType and 'NothingType. You could just
-- define datatypes called JustType and NothingType,
-- but this makes the intent clearer.
data MaybeType = JustType | NothingType

data M (t::MaybeType) a where
  -- The order of these constructors must not
  -- be changed, because this type must look,
  -- at runtime, exactly like a Maybe
  N :: M 'NothingType a
  J :: a -> M 'JustType a

-- A safe sort of fromJust for M.
fromJ :: M 'JustType a -> a
fromJ (J a) = a

-- Really, seriously unsafe.
unsafeFromJust :: Maybe a -> a
unsafeFromJust m = fromJ (unsafeCoerce m)
Run Code Online (Sandbox Code Playgroud)