这很难解释,因为整个代码有一个相当大的背景细节,需要知道才能真正了解我所说的功能.但是我会尽力让我的主要观点得到解决,并希望它足够了.如果没有,请告诉我,我会添加更多信息.所以:
我有一个Haskell函数eval :: WExp -> Memory -> WValue,它有一堆不同的自身实例用于不同的情况.现在,有关的知识WExp,Memory和WValue是不相关的.我的问题是,对于特定的实例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)
如果您知道查找成功,并且Maybe a确实是Just a,那么您可以简单地模式匹配:
let (Just val) = lookup ...
Run Code Online (Sandbox Code Playgroud)
在那里,你有你val::a的Maybe a.请注意,这是不安全的代码,如果lookup返回a ,它会不正确地抛出错误Nothing.
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)