Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在haskell中返回不同的类型_Haskell_Types - Fatal编程技术网

在haskell中返回不同的类型

在haskell中返回不同的类型,haskell,types,Haskell,Types,我对Haskell有些陌生,正在从事一个项目,我有以下代码: data Nested a = Elem a | Nested [Nested a] deriving (Eq, Show) data Symbol a = Value a | Transformation (a -> a -> a) deriving (Show) toSymbol :: [Char] -> Nested (Symbol Integer) toSymbol x |all isDigit x

我对Haskell有些陌生,正在从事一个项目,我有以下代码:

data Nested a = Elem a | Nested [Nested a] deriving (Eq, Show)
data Symbol a = Value a | Transformation (a -> a -> a) deriving (Show)


toSymbol :: [Char] -> Nested (Symbol Integer)
toSymbol x  
|all isDigit x = Elem (Value (strToInt x))
|x == "+" = Elem (Transformation (\x y -> x + y))
有没有办法避免将此函数的类型限制为嵌套(符号整数)?我想使用Symbol来表示许多不同的类型,并使用一个函数来按照以下内容对某些内容进行符号化:

toSymbol x  
|x == "1" = Elem (Value 1)
|x == "+" = Elem (Transformation (\x y -> x + y))
|x == "exampleword" = Elem (Value "word")
|x == "concatenate()" = Elem (Transformation concatTwoStrings)

我不知道像这样的函数的类型签名是什么。我能做些什么来获得类似的功能吗?

我认为不可能编写一个函数来实现这一点。一种可能的解决方案是使用类型类,它保持单函数API:

{-# LANGUAGE FlexibleInstances #-}

...

class Token a where
    toSymbol :: String -> Nested a

instance Token (Symbol Integer) where
    toSymbol x
        |all isDigit x = Elem (Value (read x))
        |x == "+" = Elem (Transformation (\x y -> x + y))
        |otherwise = error "Wrong type"

instance Token (Symbol String) where
    toSymbol "exampleword" = Elem (Value "word")
    toSymbol "concatenate()" = Elem (Transformation (++))
    toSymbol _ = error "Wrong type"

您无法找出类型签名的原因是因为您正在尝试“使函数的返回类型取决于传递的字符串(也称为依赖类型编程)的值”,该字符串的值仅在运行时可用

因此,基本上,如果您尝试说:
toSymbol::String->Nested(Symbol a)
,那么
a
取决于字符串的运行时值,这就是编译器抱怨它的原因

有许多方法可以细化类型,以便所有部分都可以组合在一起,一种可能的解决方案是使用新类型,指定符号可能具有的不同类型的值。下面是一个例子:

data Nested a = Elem a | Nested [Nested a] deriving (Eq, Show)
data Symbol a = Value a | Transformation (a -> a -> a)
data SymbolType = SInteger Integer | SString String

addSymbols :: SymbolType -> SymbolType -> SymbolType
addSymbols (SInteger a) (SInteger b) = SInteger (a+b)
addSymbols _ _ = error "Not possible"

concatSymbols :: SymbolType -> SymbolType -> SymbolType
concatSymbols (SString a) (SString b) = SString (a++b)
concatSymbols _ _ = error "Not possible"

toSymbol :: String -> Nested (Symbol SymbolType)
toSymbol x  
  |x == "1" = Elem (Value (SInteger 1))
  |x == "+" = Elem (Transformation addSymbols)
  |x == "exampleword" = Elem (Value (SString "word"))
  |x == "concatenate()" = Elem (Transformation concatSymbols)

不,这只能通过完全绕过类型系统来实现。你想用一种动态语言来处理这类事情。Haskell的方法不是首先从字符串开始,而是从Haskell代码作为DSL开始;然后编译器可以静态地推断类型,您就可以获得完整的类型安全性,而无需太多额外的语法。或者从某种自定义树ADT结构开始。但不是普通的弦!如果你需要在一个文件中保存一些数据,但我不会为细节费心。